题意:一棵树n个节点,三种操作:1、改变一条边的权值。2、查询节点a到b的路径中的边的最大值。3、将a到b路径上所有边的权值变为其相反数。
第4道树链剖分。。
剖分后,用线段树点更新实现操作1,即可,对于操作3,设区间内原最大值、最小值为a、b,则区间内的数都乘以-1之后,最大值、最小值变为:-b,-a。这里用线段树成段更新操作即可。注意的是使用lazy标记的时候,应当使用异或运算。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define maxn 10005 #define lson i<<1,l,m #define rson i<<1|1,m+1,r #define inf 0x3f3f3f3f int lazy[maxn<<2],Min[maxn<<2],Max[maxn<<2],id[maxn],top[maxn],son[maxn],fa[maxn],num[maxn],dep[maxn],next[maxn<<1],head[maxn],edge[maxn<<1],e[maxn][3]; int cnt,tot; void add(int u,int v) { edge[++tot]=v; next[tot]=head[u]; head[u]=tot; } void PushUp(int i) { Max[i]=max(Max[i<<1],Max[i<<1|1]); Min[i]=min(Min[i<<1],Min[i<<1|1]); } void neg(int i) { int t=Max[i]; Max[i]=-Min[i]; Min[i]=-t; } void PushDown(int i) { if(lazy[i]) { lazy[i<<1]^=1; lazy[i<<1|1]^=1; neg(i<<1); neg(i<<1|1); lazy[i]=0; } } void Negate(int i,int l,int r,int L,int R) { if(L<=l && r<=R) { lazy[i]^=1; neg(i); return; } PushDown(i); int m=(l+r)>>1; if(L<=m) Negate(lson,L,R); if(R>m) Negate(rson,L,R); PushUp(i); } void change(int i,int l,int r,int x,int v) { if(l==r) { Max[i]=Min[i]=v; return; } PushDown(i); int m=(l+r)>>1; if(x<=m) change(lson,x,v); else change(rson,x,v); PushUp(i); } int query(int i,int l,int r,int L,int R) { if(L<=l && r<=R) return Max[i]; PushDown(i); int m=(l+r)>>1,ans=-inf; if(L<=m) ans=max(ans,query(lson,L,R)); if(R>m) ans=max(ans,query(rson,L,R)); return ans; } void dfs(int u) { num[u]=1,son[u]=0; for(int i=head[u],v=edge[i]; i; i=next[i],v=edge[i]) if(fa[u]!=v) { fa[v]=u,dep[v]=dep[u]+1; dfs(v); num[u]+=num[v]; if(num[son[u]]<num[v]) son[u]=v; } } void dfs2(int u,int tp) { top[u]=tp,id[u]=++cnt; if(son[u]) dfs2(son[u],tp); for(int i=head[u],v=edge[i]; i; i=next[i],v=edge[i]) if(fa[u]!=v&&son[u]!=v) dfs2(v,v); } void Negate(int a,int b) { int f1=top[a],f2=top[b]; while(f1!=f2) { if(dep[f1]<dep[f2]) { swap(a,b),swap(f1,f2); } Negate(1,1,cnt,id[f1],id[a]); a=fa[f1]; f1=top[a]; } if(a==b) return; if(dep[a]>dep[b]) swap(a,b); Negate(1,1,cnt,id[son[a]],id[b]); } int find(int a,int b) { int ans=-inf,f1=top[a],f2=top[b]; while(f1!=f2) { if(dep[f1]<dep[f2]) { swap(a,b),swap(f1,f2); } ans=max(ans,query(1,1,cnt,id[f1],id[a])); a=fa[f1]; f1=top[a]; } if(a==b) return ans; if(dep[a]>dep[b]) swap(a,b); return max(ans,query(1,1,cnt,id[son[a]],id[b])); } int main() { int T,n; scanf("%d",&T); while(T--) { scanf("%d",&n); memset(Max,-inf,sizeof(Max)); memset(Min,inf,sizeof(Min)); memset(lazy,0,sizeof(lazy)); memset(head,0,sizeof(head)); fa[1]=dep[1]=cnt=tot=0; for(int i=1; i<=n-1; ++i) { scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]); add(e[i][0],e[i][1]); add(e[i][1],e[i][0]); } dfs(1); dfs2(1,1); for(int i=1; i<=n-1; ++i) { if(dep[e[i][0]]>dep[e[i][1]]) swap(e[i][0],e[i][1]); change(1,1,cnt,id[e[i][1]],e[i][2]); } char s[10]; while(scanf("%s",s)) { if(s[0]=='D') break; int a,b; scanf("%d%d",&a,&b); if(s[0]=='Q') printf("%d\n",find(a,b)); else if(s[0]=='C') change(1,1,cnt,id[e[a][1]],b); else Negate(a,b); } } return 0; }