题意

传送门

思路

树剖+动态开点线段树(每种宗教建一棵)
改宗教\(x\)改为\(y\),把\(rt_x\)上对应的叶子节点删了(值清空),再insert一个新的。

code:

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
const int M=N*55;

int n,q;
int nd,rt[N],val[N],c[N];
int ls[M],rs[M],mx[M],sum[M];
int nxt[N],to[N],head[N],ecnt;
int top[N],sz[N],son[N],dep[N],fa[N],dfn[N],Id[N],Time;

void add_edge(int u,int v) {nxt[++ecnt]=head[u];to[ecnt]=v;head[u]=ecnt;}

void P_up(int x) {
	mx[x]=max(mx[ls[x]],mx[rs[x]]);
	sum[x]=sum[ls[x]]+sum[rs[x]];
}

void Update(int &x,int l,int r,int p,int w) {	//p is dfn
	if(!x) x=++nd;
	if(l==r) {sum[x]=mx[x]=w;return;}
	int mid=(l+r)>>1;
	(p<=mid)?Update(ls[x],l,mid,p,w):Update(rs[x],mid+1,r,p,w);
	P_up(x);
}

int _mx(int o,int l,int r,int x,int y) {
	if(!o)return 0;
	if(x<=l&&r<=y) return mx[o];
	int mid=(l+r)>>1,res=0;
	if(x<=mid) res=max(res,_mx(ls[o],l,mid,x,y));
	if(y>mid) res=max(res,_mx(rs[o],mid+1,r,x,y));
	return res;
}

int _sum(int o,int l,int r,int x,int y) {
	if(!o)return 0;
	if(x<=l&&r<=y) return sum[o];
	int mid=(l+r)>>1,res=0;
	if(x<=mid) res+=_sum(ls[o],l,mid,x,y);
	if(y>mid) res+=_sum(rs[o],mid+1,r,x,y);
	return res;
}

void dfs1(int u,int lst) {
	sz[u]=1;
	for(int i=head[u];i;i=nxt[i]) {
		int v=to[i];if(v==lst)continue;
		dep[v]=dep[u]+1;fa[v]=u;
		dfs1(v,u);
		sz[u]+=sz[v];
		if(sz[v]>sz[son[u]]) {son[u]=v;}
	}
}

void dfs2(int u,int Tp) {
	top[u]=Tp;Id[dfn[u]=++Time]=u;
	if(son[u])dfs2(son[u],Tp);
	for(int i=head[u];i;i=nxt[i]) {
		int v=to[i];if(v==fa[u]||v==son[u])continue;
		dfs2(v,v);
	}
}

void Mx(int x,int y) {
	int C=c[x];int res=0;
	while(top[x]!=top[y]) {
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		res=max(res,_mx(rt[C],1,n,dfn[top[x]],dfn[x]));
		x=fa[top[x]];
	}
	if(dep[x]<dep[y])swap(x,y);
	res=max(res,_mx(rt[C],1,n,dfn[y],dfn[x]));
	printf("%d\n",res);
}

void Sum(int x,int y) {
	int C=c[x];int res=0;
	while(top[x]!=top[y]) {
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		res+=_sum(rt[C],1,n,dfn[top[x]],dfn[x]);
		x=fa[top[x]];
	}
	if(dep[x]<dep[y])swap(x,y);
	res+=_sum(rt[C],1,n,dfn[y],dfn[x]);
	printf("%d\n",res);
}

int main() {
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++) {scanf("%d%d",&val[i],&c[i]);}
	for(int i=1;i<n;i++) {
		int u,v;scanf("%d%d",&u,&v);add_edge(u,v),add_edge(v,u);
	}
	dfs1(1,0);
	dfs2(1,1);
	for(int i=1;i<=n;i++) {
		Update(rt[c[i]],1,n,dfn[i],val[i]);
	}
	
	while(q--) {
		int x,y;char ch[3];
		scanf("%s%d%d",ch,&x,&y);
		if(ch[1]=='C') {
			Update(rt[c[x]],1,n,dfn[x],0);
			Update(rt[y],1,n,dfn[x],val[x]);
			c[x]=y;
		}
		else if(ch[1]=='W'){
			Update(rt[c[x]],1,n,dfn[x],y);
			val[x]=y;
		}
		else if(ch[1]=='S') {
			Sum(x,y);
		}
		else {
			Mx(x,y);
		}
	}
	return 0;
}