Jzoj3625 旅行(travel)
非常好的树剖模板题了,直接C颗线段树上去就好了,动态开点一次写对~
#pragma GCC opitmize("O3")
#pragma G++ opitmize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 100010
#define mid (l+r>>1)
using namespace std;
struct edge{ int v,nt; } G[200010];
struct nod{ int l,r,s,m; } s[3000010];
int h[N],sz[N],top[N],son[N],f[N],d[N];
int n,m,cnt=1,tot=0,clk=0,w[N],l[N],c[N],rt[N];
inline void gmax(int& x,int y){ x<y?x=y:0; }
inline void ps(nod& x){
x.s=s[x.l].s+s[x.r].s;
x.m=max(s[x.l].m,s[x.r].m);
}
inline void adj(int x,int y){
G[++cnt]=(edge){y,h[x]}; h[x]=cnt;
G[++cnt]=(edge){x,h[y]}; h[y]=cnt;
}
void dfs(int x,int p){
d[x]=d[p]+1; sz[x]=1; f[x]=p;
for(int v,i=h[x];i;i=G[i].nt)
if(!d[v=G[i].v]){
dfs(v,x); sz[x]+=sz[v];
if(sz[v]>sz[son[x]]) son[x]=v;
}
}
void dgs(int x,int p){
top[x]=p; l[x]=++clk;
if(son[x]) dgs(son[x],p);
for(int v,i=h[x];i;i=G[i].nt)
if(!l[v=G[i].v]) dgs(v,v);
}
void insert(int l,int r,int& x,int p,int k){
if(!x) x=++tot;
if(l==r) { s[x].s=s[x].m=k; return; }
if(p<=mid) insert(l,mid,s[x].l,p,k);
else insert(mid+1,r,s[x].r,p,k);
ps(s[x]);
}
void remove(int l,int r,int& x,int p){
if(l==r){ x=0; return; }
if(p<=mid) remove(l,mid,s[x].l,p);
else remove(mid+1,r,s[x].r,p);
if(s[x].l || s[x].r) ps(s[x]); else x=0;
}
void modify(int l,int r,int x,int p,int k){
if(l==r){ s[x].s=s[x].m=k; return; }
if(p<=mid) modify(l,mid,s[x].l,p,k);
else modify(mid+1,r,s[x].r,p,k);
ps(s[x]);
}
int queryS(int l,int r,int x,int L,int R){
if(!x) return 0;
if(L<=l && r<=R) return s[x].s;
int ans=0;
if(L<=mid) ans+=queryS(l,mid,s[x].l,L,R);
if(mid<R) ans+=queryS(mid+1,r,s[x].r,L,R);
return ans;
}
int gSum(int x,int y){
int ans=0,C=c[x];
for(;top[x]!=top[y];y=f[top[y]]){
if(d[top[x]]>d[top[y]]) swap(x,y);
ans+=queryS(1,n,rt[C],l[top[y]],l[y]);
}
if(d[x]>d[y]) swap(x,y);
return ans+queryS(1,n,rt[C],l[x],l[y]);
}
int queryM(int l,int r,int x,int L,int R){
if(!x) return 0;
if(L<=l && r<=R) return s[x].m;
int ans=0;
if(L<=mid) gmax(ans,queryM(l,mid,s[x].l,L,R));
if(mid<R) gmax(ans,queryM(mid+1,r,s[x].r,L,R));
return ans;
}
int gMax(int x,int y){
int ans=0,C=c[x];
for(;top[x]!=top[y];y=f[top[y]]){
if(d[top[x]]>d[top[y]]) swap(x,y);
gmax(ans,queryM(1,n,rt[C],l[top[y]],l[y]));
}
if(d[x]>d[y]) swap(x,y);
return max(ans,queryM(1,n,rt[C],l[x],l[y]));
}
int main(){
freopen("travel.in","r",stdin);
freopen("travel.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d%d",w+i,c+i);
for(int x,y,i=1;i<n;++i) scanf("%d%d",&x,&y),adj(x,y);
dfs(1,0); dgs(1,1); char o[3];
for(int i=1;i<=n;++i) insert(1,n,rt[c[i]],l[i],w[i]);
for(int x,y;m--;){
scanf("%s%d%d",o,&x,&y);
if(*o=='C'){
if(o[1]=='C'){
remove(1,n,rt[c[x]],l[x]);
insert(1,n,rt[y],l[x],w[x]);
c[x]=y;
} else {
modify(1,n,rt[c[x]],l[x],y);
w[x]=y;
}
} else {
if(o[1]=='S') printf("%d\n",gSum(x,y));
else printf("%d\n",gMax(x,y));
}
}
}