[POJ3237]树的维护 树链剖分+线段树
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define N 110000 #define inf 0x3fffffff int n; int e[N],w[N],ne[N],v[N]; int nn=0; void add(int x,int y,int z){ ne[++nn]=e[x],e[x]=nn,v[nn]=y,w[nn]=z; } int dp[N],top[N],fa[N],val[N]; int q[N],he,bo; int we[N],siz[N],num[N],rk[N]; int tot; struct node{ int l,r,maxx,e,minn; }t[N*4]; void down(int x){ if(t[x].e){ t[x<<1].e^=1; t[(x<<1)+1].e^=1; int u=t[x<<1].maxx; t[x<<1].maxx=-t[x<<1].minn; t[x<<1].minn=-u; u=t[(x<<1)+1].maxx; t[(x<<1)+1].maxx=-t[(x<<1)+1].minn; t[(x<<1)+1].minn=-u; t[x].e=0; } } void build(int l,int r,int k){ t[k].l=l,t[k].r=r; if(l==r){ t[k].minn=t[k].maxx=val[num[l]]; return; } int mid=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,(k<<1)+1); t[k].maxx=max(t[k<<1].maxx,t[(k<<1)+1].maxx); t[k].minn=min(t[k<<1].minn,t[(k<<1)+1].minn); } void rev(int l,int r,int k){ if(t[k].l>=l&&t[k].r<=r){ t[k].e^=1; int u=t[k].maxx; t[k].maxx=-t[k].minn; t[k].minn=-u; return; } down(k); if(t[k<<1].l<=r&&t[k<<1].r>=l)rev(l,r,k<<1); if(t[(k<<1)+1].l<=r&&t[(k<<1)+1].r>=l)rev(l,r,(k<<1)+1); t[k].maxx=max(t[k<<1].maxx,t[(k<<1)+1].maxx); t[k].minn=min(t[k<<1].minn,t[(k<<1)+1].minn); } int ans; void ask(int l,int r,int k){ if(t[k].l>=l&&t[k].r<=r){ ans=max(ans,t[k].maxx); return; } down(k); if(t[k<<1].l<=r&&t[k<<1].r>=l)ask(l,r,k<<1); if(t[(k<<1)+1].l<=r&&t[(k<<1)+1].r>=l)ask(l,r,(k<<1)+1); } void change(int l,int k,int y){ if(t[k].l==t[k].r){ t[k].maxx=y; t[k].minn=y; return; } down(k); if(t[k<<1].r>=l)change(l,k<<1,y); else change(l,(k<<1)+1,y); t[k].maxx=max(t[k<<1].maxx,t[(k<<1)+1].maxx); t[k].minn=min(t[k<<1].minn,t[(k<<1)+1].minn); } int ASK(int l,int r){ ans=-inf; ask(l,r,1); return ans; } void dfs(int x,int ff,int tp){ num[++tot]=x; rk[x]=tot; top[x]=tp; if(we[x])dfs(we[x],x,tp); for(int i=e[x];i;i=ne[i])if(v[i]!=ff&&we[x]!=v[i]){ dfs(v[i],x,v[i]); } } int Ask(int x,int y){ int kk=-inf; while(1){ if(top[x]==top[y]){ if(x==y)break; if(dp[x]<dp[y])swap(x,y); kk=max(kk,ASK(rk[y]+1,rk[x])); break; } if(dp[top[x]]>dp[top[y]])swap(x,y); kk=max(kk,ASK(rk[top[y]],rk[y])); y=fa[top[y]]; } return kk; } void REV(int x,int y){ while(1){ if(top[x]==top[y]){ if(x==y)break; if(dp[x]<dp[y])swap(x,y); rev(rk[y]+1,rk[x],1); break; } if(dp[top[x]]>dp[top[y]])swap(x,y); rev(rk[top[y]],rk[y],1); y=fa[top[y]]; } } char in[10]; int main(){ scanf("%d",&n); int x,i; for(i=1;i<n;i++){ int a,b,c; scanf("%d%d%d",&a,&b,&c); add(a,b,c); add(b,a,c); } q[he=bo=1]=1; while(he>=bo)for(i=e[x=q[bo++]];i;i=ne[i])if(fa[x]!=v[i])fa[v[i]]=x,q[++he]=v[i],dp[v[i]]=dp[x]+1,val[v[i]]=w[i]; for(i=he;i>=1;i--){ siz[q[i]]=1; for(int j=e[q[i]];j;j=ne[j])if(fa[q[i]]!=v[j]){ siz[q[i]]+=siz[v[j]]; if(!we[q[i]]||siz[v[j]]>siz[we[q[i]]])we[q[i]]=v[j]; } } dfs(1,0,1); build(1,n,1); while(1){ int a,b; scanf("%s",in); if(in[0]=='D')break; if(in[0]=='N'){ scanf("%d%d",&a,&b); REV(a,b); } if(in[0]=='C'){ scanf("%d%d",&a,&b); if(dp[v[a<<1]]>dp[v[(a<<1)-1]])a=v[a<<1]; else a=v[(a<<1)-1]; change(rk[a],1,b); } if(in[0]=='Q'){ scanf("%d%d",&a,&b); printf("%d\n",Ask(a,b)); } } }