很明显,这是一个树上操作,但是需要类似线段树的维护,一个很裸的树链剖分加线段树。
因为有c个宗教,那么就开c棵线段树。然后就可以了。
我用了动态开空间,类似主席树那样打。在线大法好!
也可以打一个离散化。离线大法好!
#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=100007;
int i,j,k,l,n,m,ans;
int first[maxn*2],next[maxn*2],last[maxn*2],a[maxn],b[maxn],num,tot;
int size[maxn],fa[maxn],deep[maxn],son[maxn],w[maxn],sum;
int root[maxn],top[maxn];
bool bz[maxn];
char s[5];
struct node{
int l,r,sum,da;
}t[maxn*50];
void add(int x,int y){
last[++num]=y;
next[num]=first[x];
first[x]=num;
last[++num]=x;
next[num]=first[y];
first[y]=num;
}
void dfs1(int x,int y){
int i,j=0,k=0;
size[x]=1;
for(i=first[x];i;i=next[i]){
if(last[i]!=y){
fa[last[i]]=x;
deep[last[i]]=deep[x]+1;
dfs1(last[i],x);
size[x]+=size[last[i]];
if(klast[i]]){
k=size[last[i]];
son[x]=last[i];
}
}
}
}
void dfs2(int x,int y){
top[x]=y;
w[x]=++tot;
if(!son[x]) return;
dfs2(son[x],y);
for(int i=first[x];i;i=next[i]){
if(last[i]!=fa[x]&&last[i]!=son[x]){
dfs2(last[i],last[i]);
}
}
}
void change(int &x,int l,int r,int y,int z){
if(x==0)x=++sum;
if(l==r){t[x].da=t[x].sum=z;return;}
int mid=(l+r)/2;
if(y<=mid)change(t[x].l,l,mid,y,z);
else change(t[x].r,mid+1,r,y,z);
t[x].sum=t[t[x].l].sum+t[t[x].r].sum;
t[x].da=max(t[t[x].l].da,t[t[x].r].da);
}
int findsum(int x,int l,int r,int y,int z){
if(x==0)return 0;
if(y>z)return 0;
if(l==y&&r==z){
return t[x].sum;
}
else{
int mid=(l+r)/2;
if(z<=mid)return findsum(t[x].l,l,mid,y,z);
else if(y>mid)return findsum(t[x].r,mid+1,r,y,z);
else{
return findsum(t[x].l,l,mid,y,mid)+findsum(t[x].r,mid+1,r,mid+1,z);
}
}
}
int findda(int x,int l,int r,int y,int z){
if(x==0)return 0;
if(y>z)return 0;
if(l==y&&r==z){
return t[x].da;
}
else{
int mid=(l+r)/2;
if(z<=mid)return findda(t[x].l,l,mid,y,z);
else if(y>mid)return findda(t[x].r,mid+1,r,y,z);
else{
return max(findda(t[x].l,l,mid,y,mid),findda(t[x].r,mid+1,r,mid+1,z));
}
}
}
int zhaoda(int x,int y,int z){
int f1=top[x],f2=top[y],o=-0x7fffffff;
while(f1!=f2){
if(deep[f1]x,y);
swap(f1,f2);
}
o=max(o,findda(root[z],1,n,w[f1],w[x]));
x=fa[f1];f1=top[x];
}
if(deep[x]y])swap(x,y);
return o=max(o,findda(root[z],1,n,w[y],w[x]));
}
int zhaosum(int x,int y,int z){
int f1=top[x],f2=top[y],o=0;
while(f1!=f2){
if(deep[f1]x,y);
}
o+=findsum(root[z],1,n,w[f1],w[x]);
x=fa[f1];f1=top[x];
}
if(deep[x]y])swap(x,y);
return o+=findsum(root[z],1,n,w[y],w[x]);
}
int main(){
// freopen("travel.in","r",stdin);
// freopen("travel.out","w",stdout);
scanf("%d%d",&n,&m);
fo(i,1,n){
scanf("%d%d",&a[i],&b[i]);
}
fo(i,1,n-1){
scanf("%d%d",&k,&l);
add(k,l);
}
deep[1]=1;
dfs1(1,0);
dfs2(1,1);
fo(i,1,n){
change(root[b[i]],1,n,w[i],a[i]);
}
fo(i,1,m){
scanf("%s%d%d",s+1,&k,&l);
if(s[1]=='C'){
if(s[2]=='C'){
change(root[b[k]],1,n,w[k],0);
b[k]=l;
change(root[b[k]],1,n,w[k],a[k]);
}
else{
a[k]=l;
change(root[b[k]],1,n,w[k],l);
}
}
else{
if(s[2]=='S'){
ans=zhaosum(k,l,b[k]);
printf("%d\n",ans);
}
else{
ans=zhaoda(k,l,b[k]);
printf("%d\n",ans);
}
if(ans==8469){
int opp=1;
}
}
}
}