对每一个宗教建一棵线段树,然后树剖搞搞
#include <iostream>
#include <cstdio>
using namespace std;
int n, m, w[100005], c[100005], uu, vv, hea[100005], cnt, dep[100005];
int fa[100005], top[100005], idx[100005], qaq, siz[100005], son[100005];
int rot[100005], orz, zdz[5000005], sum[5000005], lson[5000005];
int rson[5000005];
char ss[15];
struct Edge{
int too, nxt, val;
}edge[200005];
void add_edge(int fro, int too){
edge[++cnt].nxt = hea[fro];
edge[cnt].too = too;
hea[fro] = cnt;
}
void dfs1(int x, int f){
fa[x] = f;
siz[x] = 1;
dep[x] = dep[f] + 1;
int maxSon=-1;
for(int i=hea[x]; i; i=edge[i].nxt){
int t=edge[i].too;
if(t!=f){
dfs1(t, x);
siz[x] += siz[t];
if(maxSon<siz[t]) maxSon = siz[t], son[x] = t;
}
}
}
void dfs2(int x, int topf){
top[x] = topf;
idx[x] = ++qaq;
if(!son[x]) return ;
dfs2(son[x], topf);
for(int i=hea[x]; i; i=edge[i].nxt){
int t=edge[i].too;
if(t!=fa[x] && t!=son[x])
dfs2(t, t);
}
}
void pushUp(int o){
sum[o] = sum[lson[o]] + sum[rson[o]];
zdz[o] = max(zdz[lson[o]], zdz[rson[o]]);
}
void insert(int &o, int l, int r, int x, int w){
if(!o) o = ++orz;
if(l==r) sum[o] = zdz[o] = w;
else{
int mid=(l+r)>>1;
if(x<=mid) insert(lson[o], l, mid, x, w);
if(mid<x) insert(rson[o], mid+1, r, x, w);
pushUp(o);
}
}
void clr(int &o){
lson[o] = rson[o] = sum[o] = zdz[o] = 0;
o = 0;
}
void shanchu(int &o, int l, int r, int x){
if(l==r) clr(o);
else{
int mid=(l+r)>>1;
if(x<=mid) shanchu(lson[o], l, mid, x);
if(mid<x) shanchu(rson[o], mid+1, r, x);
pushUp(o);
if(lson[o]+rson[o]==0) clr(o);
}
}
int querySGTSum(int o, int l, int r, int x, int y){
if(!o) return 0;
if(l>=x && r<=y) return sum[o];
else{
int mid=(l+r)>>1;
int ans=0;
if(x<=mid) ans += querySGTSum(lson[o], l, mid, x, y);
if(mid<y) ans += querySGTSum(rson[o], mid+1, r, x, y);
return ans;
}
}
int querySGTMax(int o, int l, int r, int x, int y){
if(!o) return 0;
if(l>=x && r<=y) return zdz[o];
else{
int mid=(l+r)>>1;
int ans=0;
if(x<=mid) ans = max(ans, querySGTMax(lson[o], l, mid, x, y));
if(mid<y) ans = max(ans, querySGTMax(rson[o], mid+1, r, x, y));
return ans;
}
}
int querySum(int uu, int vv){
int bel=c[uu], ans=0;
while(top[uu]!=top[vv]){
if(dep[top[uu]]<dep[top[vv]]) swap(uu, vv);
ans += querySGTSum(rot[bel], 1, n, idx[top[uu]], idx[uu]);
uu = fa[top[uu]];
}
if(dep[uu]>dep[vv]) swap(uu, vv);
ans += querySGTSum(rot[bel], 1, n, idx[uu], idx[vv]);
return ans;
}
int queryMax(int uu, int vv){
int bel=c[uu], ans=0;
while(top[uu]!=top[vv]){
if(dep[top[uu]]<dep[top[vv]]) swap(uu, vv);
ans =max(ans, querySGTMax(rot[bel], 1, n, idx[top[uu]], idx[uu]));
uu = fa[top[uu]];
}
if(dep[uu]>dep[vv]) swap(uu, vv);
ans = max(ans, querySGTMax(rot[bel], 1, n, idx[uu], idx[vv]));
return ans;
}
int main(){
cin>>n>>m;
for(int i=1; i<=n; i++) scanf("%d %d", &w[i], &c[i]);
for(int i=1; i<n; i++){
scanf("%d %d", &uu, &vv);
add_edge(uu, vv);
add_edge(vv, uu);
}
dep[1] = 1;
dfs1(1, 0);
dfs2(1, 1);
for(int i=1; i<=n; i++)
insert(rot[c[i]], 1, n, idx[i], w[i]);
while(m--){
scanf("%s %d %d", ss, &uu, &vv);
if(ss[0]==‘C‘ && ss[1]==‘C‘){
shanchu(rot[c[uu]], 1, n, idx[uu]);
c[uu] = vv;
insert(rot[c[uu]], 1, n, idx[uu], w[uu]);
}
if(ss[0]==‘C‘ && ss[1]==‘W‘){
w[uu] = vv;
insert(rot[c[uu]], 1, n, idx[uu], w[uu]);
}
if(ss[0]==‘Q‘ && ss[1]==‘S‘)
printf("%d\n", querySum(uu, vv));
if(ss[0]==‘Q‘ && ss[1]==‘M‘)
printf("%d\n", queryMax(uu, vv));
}
return 0;
}