题意:有n个城市,每个城市有权值和颜色,支持的操作有单点修改权值,单点修改颜色,查询区间同颜色之和,查询区间同颜色最大值。
思路:对于每种颜色,放入不同的线段树,但其实整个加起来还是还是n个结点,值得注意的是,这里要使用动态开点,要一步步记录左右儿子的编号,而不能使用2i,2i+1直接去找,而这样建树的话,就可以很方便的查询同颜色的结点了,修改操作啥的把原颜色中的结点改为0,再在现在的颜色中开点就可以了。
#include <cstdio>
#include <algorithm>
#define Rep(i,s,t) for(int i=s;i<=t;i++)
#define For(i,s,t) for(int i=s;i;i=t)
using namespace std;
const int maxx = 100000 + 25;
const int maxm = 4000000 + 25;
const int Inf = (unsigned)(-1) >> 1;
int head[maxx],nxt[maxx<<1],to[maxx<<1],a[maxx],c[maxx];
int top[maxx],rnk[maxx],size[maxx],dpt[maxx],ftr[maxx],son[maxx];
int T[maxm],Tmax[maxm],lc[maxm],rc[maxm],rt[maxx];
int num,cnt,tot,n,m,x,y,k;
char f[8];
namespace Y{
void Ins(int x,int y) {to[++num]=y;nxt[num]=head[x];head[x]=num;}
void Dfs1(int x){
size[x] = 1;
For( i , head[x] , nxt[i] ){
int now = to[i];if(now == ftr[x]) continue;
dpt[now] = dpt[x] + 1;ftr[now] = x;
Dfs1(now);size[x] += size[now];
if(size[now] > size[son[x]]) son[x] = now;
}
}
void Dfs2(int x,int brn){
rnk[x] = ++cnt;top[x] = brn;
if(son[x]) Dfs2(son[x],brn);
For( i , head[x] , nxt[i] )
if(to[i] != ftr[x] && to[i] != son[x])
Dfs2(to[i],to[i]);
}
void upt(int i){
T[i] = T[lc[i]] + T[rc[i]];
Tmax[i] = max(Tmax[lc[i]],Tmax[rc[i]]);
}
void modify(int &i,int pos,int l,int r,int k){
if(!i) i = ++tot;if(l == r) {T[i] = Tmax[i] = k;return;}
int mid = (l+r) >> 1;
if(pos <= mid) modify(lc[i],pos,l,mid,k);
if(pos > mid) modify(rc[i],pos,mid+1,r,k);
upt(i);
}
void chk(int &tmp,int pls,int flag){
if(flag == 0) tmp = tmp + pls;
if(flag == 1) tmp = max(tmp,pls);
}
int Query(int i,int x,int y,int l,int r,int flag){
if(x <= l && r <= y) return flag? Tmax[i] : T[i];
int ans = (flag)? -Inf : 0;int mid = (l+r) >> 1;
if(x <= mid) chk(ans,Query(lc[i],x,y,l,mid,flag),flag);
if(y > mid) chk(ans,Query(rc[i],x,y,mid+1,r,flag),flag);
return ans;
}
int Get(int i,int x,int y,int flag){
int ans = (flag)? -Inf : 0;
while(top[x] != top[y]){
if(dpt[top[x]] > dpt[top[y]]) x^=y^=x^=y;
chk(ans,Query(i,rnk[top[y]],rnk[y],1,n,flag),flag);
y = ftr[top[y]];
}
if(rnk[x] > rnk[y]) x^=y^=x^=y;
chk(ans,Query(i,rnk[x],rnk[y],1,n,flag),flag);
return ans;
}
}
using namespace Y;
int main(){
scanf("%d%d",&n,&m);
Rep( i , 1 , n ) scanf("%d%d",&a[i],&c[i]);
Rep( i , 1 , n-1 ) scanf("%d%d",&x,&y),Ins(x,y),Ins(y,x);
Dfs1(1),Dfs2(1,1);Rep( i , 1 , n ) modify(rt[c[i]],rnk[i],1,n,a[i]);
while( m-- ){
scanf("%s",f);
if(f[1] == 'S') scanf("%d%d",&x,&y),printf("%d\n",Get(rt[c[x]],x,y,0));
if(f[1] == 'C'){
scanf("%d%d",&x,&y);
modify(rt[c[x]],rnk[x],1,n,0);
c[x]=y;
modify(rt[c[x]],rnk[x],1,n,a[x]);
}
if(f[1] == 'W')
scanf("%d%d",&x,&y),a[x]=y,modify(rt[c[x]],rnk[x],1,n,a[x]);
if(f[1] == 'M') scanf("%d%d",&x,&y),printf("%d\n",Get(rt[c[x]],x,y,1));
}
return 0;
}