poj 3237 Tree
给一棵边权树,再给三个操作。第一个把一条边权改为v,第二个将一条链的值取反,第三个求一条链的最大值。
考虑用线段树维护连续区间的最大最小值。区间取反打lazy标记,如果lazy是奇数就取反再把最大最小值交换下放,否则不管,单点更新和区间查询很简单。
最后用树剖更新区间。把边权映射到点权即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #define Lson l,mid,rt<<1 #define Rson mid+1,r,rt<<1|1 using namespace std; const int M = 1e5+7; typedef long long ll; int _,n,pp; int cnt,tot,head[M],p[M]; int sz[M],son[M],dep[M],f[M],top[M],rnk[M],id[M]; ll a[M]; char s[10]; struct edge { int v,next; ll w; }e[M<<1]; struct node { ll mx,mn;int lazy; }tree[M<<2]; void init(){ tot=cnt=0;memset(head,-1,sizeof(head)); } void add(int u,int v,ll w){ e[++cnt].v=v;e[cnt].w=w;e[cnt].next=head[u]; head[u]=cnt; } void fsd(int u,int fa){ for(int i=head[u];~i;i=e[i].next){ int v=e[i].v;ll w=e[i].w; if(v==fa) continue; a[v]=w;p[(i-1)/2+1]=v; fsd(v,u); } return ; } void dfs(int u,int fa,int d){ sz[u]=1;f[u]=fa;son[u]=-1;dep[u]=d; for(int i=head[u];~i;i=e[i].next){ int v=e[i].v; if(v==fa) continue; dfs(v,u,d+1); sz[u]+=sz[v]; if(son[u]==-1||sz[v]>sz[son[u]]) son[u]=v; } return ; } void dfs1(int u,int t){ id[u]=++tot; rnk[tot]=u; top[u]=t; if(son[u]==-1) return; dfs1(son[u],t); for(int i=head[u];~i;i=e[i].next){ int v=e[i].v; if(v==f[u]||v==son[u]) continue; dfs1(v,v); } return ; } void Pushup(int rt){ tree[rt].mx=max(tree[rt<<1].mx,tree[rt<<1|1].mx); tree[rt].mn=min(tree[rt<<1].mn,tree[rt<<1|1].mn); } void Pushdown(int rt){ if(tree[rt].lazy){ int v=tree[rt].lazy; tree[rt].lazy=0; if(v%2==0){ return ; } tree[rt<<1].mn*=-1;tree[rt<<1].mx*=-1; tree[rt<<1|1].mn*=-1;tree[rt<<1|1].mx*=-1; swap(tree[rt<<1].mn,tree[rt<<1].mx); swap(tree[rt<<1|1].mx,tree[rt<<1|1].mn); tree[rt<<1].lazy+=v;tree[rt<<1|1].lazy+=v; } } void build(int l,int r,int rt){ tree[rt].mx=-1e15,tree[rt].mn=1e15;tree[rt].lazy=0; if(l==r){ tree[rt].mx=tree[rt].mn=a[rnk[l]]; return ; } int mid=(l+r)>>1; build(Lson); build(Rson); Pushup(rt); } void update(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R){ tree[rt].lazy++; tree[rt].mx*=-1;tree[rt].mn*=-1; swap(tree[rt].mx,tree[rt].mn); return ; } Pushdown(rt); int mid=(l+r)>>1; if(L<=mid) update(L,R,Lson); if(R>mid) update(L,R,Rson); Pushup(rt); return ; } void change(int l,int r,int rt,ll v){ if(l==r){ tree[rt].mx=tree[rt].mn=v; return ; } Pushdown(rt); int mid=(l+r)>>1; if(pp<=mid) change(Lson,v); else change(Rson,v); Pushup(rt); } ll query(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R){ return tree[rt].mx; } Pushdown(rt); int mid=(l+r)>>1;ll res=-1e15; if(L<=mid) res=max(res,query(L,R,Lson)); if(R>mid) res=max(res,query(L,R,Rson)); return res; } void updates(int x,int y){ int fx=top[x],fy=top[y]; while(fx!=fy){ if(dep[fx]>dep[fy]){ update(id[fx],id[x],1,n,1); x=f[fx],fx=top[x]; } else{ update(id[fy],id[y],1,n,1); y=f[fy],fy=top[y]; } } if(x==y) return ; if(dep[x]<dep[y]) update(id[son[x]],id[y],1,n,1); else update(id[son[y]],id[x],1,n,1); } ll sum(int x,int y){ int fx=top[x],fy=top[y];ll res=-1e15; while(fx!=fy){ if(dep[fx]>dep[fy]){ res=max(res,query(id[fx],id[x],1,n,1)); x=f[fx],fx=top[x]; } else{ res=max(res,query(id[fy],id[y],1,n,1)); y=f[fy],fy=top[y]; } } if(x==y) return res; if(dep[x]<dep[y]) res=max(res,query(id[son[x]],id[y],1,n,1)); else res=max(res,query(id[son[y]],id[x],1,n,1)); return res; } int main(){ freopen("1.in","r",stdin); freopen("1.out","w",stdout); scanf("%d",&_); while(_--){ init(); scanf("%d",&n); for(int i=1;i<n;i++){ int u,v;ll w; scanf("%d%d%lld",&u,&v,&w); add(u,v,w);add(v,u,w); } fsd(1,-1);a[1]=0ll; dfs(1,-1,1); dfs1(1,1); build(1,n,1); while(1){ scanf("%s",s); if(s[0]=='D') break; if(s[0]=='C'){ int a;ll b; scanf("%d%lld",&a,&b);pp=id[p[a]]; change(1,n,1,b); } if(s[0]=='N'){ int a,b; scanf("%d%d",&a,&b); updates(a,b); } if(s[0]=='Q'){ int a,b; scanf("%d%d",&a,&b); printf("%lld\n",sum(a,b)); } } } return 0; }