[BZOJ]3531: [Sdoi2014]旅行
题目大意:给定一棵树,每个点有颜色和权值,支持修改一个点的颜色和权值,查询一条链上某种颜色的和与最大值。(n<=10^5)
思路:树剖一下,每种颜色开一棵线段树,动态开点,时间复杂度O(nlogn^2),空间复杂度O(nlogn)。
#include<cstdio> #include<algorithm> using namespace std; inline int read() { int x;char c; while((c=getchar())<'0'||c>'9'); for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=(x<<3)+(x<<1)+c-'0'; return x; } #define MN 100000 #define ND 4000000 struct edge{int nx,t;}e[MN*2+5]; int h[MN+5],en,w[MN+5],c[MN+5],l[MN+5],f[MN+5],cnt; int s[MN+5],mx[MN+5],d[MN+5],fa[MN+5],rt[MN+5],tn; struct node{int l,r,sm,mx;}t[ND+5]; inline void ins(int x,int y) { e[++en]=(edge){h[x],y};h[x]=en; e[++en]=(edge){h[y],x};h[y]=en; } void pre(int x) { s[x]=1; for(int i=h[x];i;i=e[i].nx)if(e[i].t!=fa[x]) { d[e[i].t]=d[x]+1;fa[e[i].t]=x; pre(e[i].t); s[x]+=s[e[i].t]; if(s[e[i].t]>s[mx[x]])mx[x]=e[i].t; } } void dfs(int x,int k) { l[x]=++cnt;f[x]=k; if(mx[x])dfs(mx[x],k); for(int i=h[x];i;i=e[i].nx) if(e[i].t!=fa[x]&&e[i].t!=mx[x])dfs(e[i].t,e[i].t); } inline void up(int k) { t[k].sm=t[t[k].l].sm+t[t[k].r].sm; t[k].mx=max(t[t[k].l].mx,t[t[k].r].mx); } void change(int&k,int l,int r,int x,int z) { if(!k)k=++tn; if(l==r){t[k].sm=t[k].mx=z;return;} int mid=l+r>>1; if(x>mid)change(t[k].r,mid+1,r,x,z); else change(t[k].l,l,mid,x,z); up(k); } int querymx(int k,int l,int r,int L,int R) { if(l==L&&r==R)return t[k].mx; int mid=l+r>>1; if(R<=mid)return querymx(t[k].l,l,mid,L,R); if(L>mid)return querymx(t[k].r,mid+1,r,L,R); return max(querymx(t[k].l,l,mid,L,mid),querymx(t[k].r,mid+1,r,mid+1,R)); } int querysm(int k,int l,int r,int L,int R) { if(l==L&&r==R)return t[k].sm; int mid=l+r>>1; if(R<=mid)return querysm(t[k].l,l,mid,L,R); if(L>mid)return querysm(t[k].r,mid+1,r,L,R); return querysm(t[k].l,l,mid,L,mid)+querysm(t[k].r,mid+1,r,mid+1,R); } int querysm(int c,int x,int y) { int res=0; while(f[x]!=f[y]) if(d[f[x]]>d[f[y]])res+=querysm(rt[c],1,MN,l[f[x]],l[x]),x=fa[f[x]]; else res+=querysm(rt[c],1,MN,l[f[y]],l[y]),y=fa[f[y]]; return res+querysm(rt[c],1,MN,min(l[x],l[y]),max(l[x],l[y])); } int querymx(int c,int x,int y) { int res=0; while(f[x]!=f[y]) if(d[f[x]]>d[f[y]])res=max(res,querymx(rt[c],1,MN,l[f[x]],l[x])),x=fa[f[x]]; else res=max(res,querymx(rt[c],1,MN,l[f[y]],l[y])),y=fa[f[y]]; return max(res,querymx(rt[c],1,MN,min(l[x],l[y]),max(l[x],l[y]))); } int main() { int n=read(),q=read(),i,x,y;char t[5]; for(i=1;i<=n;++i)w[i]=read(),c[i]=read(); for(i=1;i<n;++i)ins(read(),read()); pre(1);dfs(1,1); for(i=1;i<=n;++i)change(rt[c[i]],1,MN,l[i],w[i]); while(q--) { scanf("%s",t);x=read();y=read(); if(t[1]=='C') change(rt[c[x]],1,MN,l[x],0), change(rt[c[x]=y],1,MN,l[x],w[x]); if(t[1]=='W') change(rt[c[x]],1,MN,l[x],w[x]=y); if(t[1]=='S')printf("%d\n",querysm(c[x],x,y)); if(t[1]=='M')printf("%d\n",querymx(c[x],x,y)); } }