题意
思路
树剖+动态开点线段树(每种宗教建一棵)
改宗教\(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;
}