[题解]luogu_P3313_旅行(树剖
树剖,其实信仰就是颜色,对于这种颜色问题我们可以考虑维护每种颜色的位置,对每种颜色用数据结构维护,可以支持合并之类的一些操作,这里可以对每个颜色维护一个动态开点权值线段树,线段树维护此颜色某点的权值,没有就是不在这个颜色里,修改直接删除再修改之类的即可
#include<bits/stdc++.h> #define mid ((l+r)>>1) using namespace std; const int maxn=100009; int n,m,w[maxn],c[maxn],tot; struct node{ int v,nxt; }e[maxn<<1]; int head[maxn],cnt; inline void add(int u,int v){ e[++cnt].v=v;e[cnt].nxt=head[u];head[u]=cnt; } int fa[maxn],dep[maxn],siz[maxn],son[maxn],dfn[maxn],id[maxn],top[maxn]; void dfs1(int x,int f){ siz[x]=1;dep[x]=dep[f]+1;fa[x]=f; for(int i=head[x];i;i=e[i].nxt){ int y=e[i].v;if(y==f)continue; dfs1(y,x); siz[x]+=siz[y]; if(siz[y]>siz[son[x]])son[x]=y; } } void dfs2(int x,int tp){ top[x]=tp; dfn[x]=++tot; id[tot]=x; if(!son[x])return; dfs2(son[x],tp); for(int i=head[x];i;i=e[i].nxt){ int y=e[i].v;if(y==fa[x]||y==son[x])continue; dfs2(y,y); } } int root[maxn],ls[maxn*30],rs[maxn*30]; struct ttt{ int mx,sum; }t[maxn*30]; inline void upd(int x){ t[x].sum=t[ls[x]].sum+t[rs[x]].sum; t[x].mx=max(t[ls[x]].mx,t[rs[x]].mx); } inline void change(int &x,int l,int r,int pos,int val){//dfs序为pos,评级val if(!x)x=++tot; t[x].mx=max(t[x].mx,val),t[x].sum+=val; if(l==r)return; if(pos<=mid)change(ls[x],l,mid,pos,val); else change(rs[x],mid+1,r,pos,val); } inline void del(int &x,int l,int r,int pos){ if(l==r){ t[x].sum=t[x].mx=0;return; } if(pos<=mid)del(ls[x],l,mid,pos); else del(rs[x],mid+1,r,pos); upd(x); } inline int qSum(int x,int l,int r,int L,int R){ if(L<=l&&r<=R)return t[x].sum; int ans=0; if(L<=mid)ans+=qSum(ls[x],l,mid,L,R); if(R>mid)ans+=qSum(rs[x],mid+1,r,L,R); return ans; } inline int qMx(int x,int l,int r,int L,int R){ if(L<=l&&r<=R)return t[x].mx; int ans=0; if(L<=mid)ans=max(ans,qMx(ls[x],l,mid,L,R)); if(R>mid)ans=max(ans,qMx(rs[x],mid+1,r,L,R)); return ans; } inline int qMxRoute(int x,int y,int val){ int ans=0; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y); ans=max(ans,qMx(root[val],1,n,dfn[top[x]],dfn[x])); x=fa[top[x]]; } if(dep[x]<dep[y])swap(x,y); ans=max(ans,qMx(root[val],1,n,dfn[y],dfn[x])); return ans; } inline int qSumRoute(int x,int y,int val){ int ans=0; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y); ans+=qSum(root[val],1,n,dfn[top[x]],dfn[x]); x=fa[top[x]]; } if(dep[x]<dep[y])swap(x,y); ans+=qSum(root[val],1,n,dfn[y],dfn[x]); return ans; } int main(){ // freopen("test.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d%d",&w[i],&c[i]); for(int i=1,u,v;i<n;i++){ scanf("%d%d",&u,&v);add(u,v);add(v,u); } dfs1(1,0);dfs2(1,1); for(int i=1;i<=n;i++)change(root[c[i]],1,n,dfn[i],w[i]); char op[10]; for(int i=1,x,y;i<=m;i++){ scanf("%s",op); scanf("%d%d",&x,&y); if(op[1]=='C'){ del(root[c[x]],1,n,dfn[x]); change(root[y],1,n,dfn[x],w[x]); c[x]=y; } else if(op[1]=='W'){ del(root[c[x]],1,n,dfn[x]); change(root[c[x]],1,n,dfn[x],y); w[x]=y; } else if(op[1]=='S')printf("%d\n",qSumRoute(x,y,c[x])); else printf("%d\n",qMxRoute(x,y,c[x])); } }