题目传送门
。
解法:
据说叫动态开点。
需要用的点才建线段树。
那么最多只有二十万种不同的信息。。
跟主席树一样嘛。
YY就好了
代码实现:
#include
#include
#include
#include
#include
#include
#include
using namespace std;
struct node {int x,y,next;}a[210000];int len,last[110000];
void ins(int x,int y) {len++;a[len].x=x;a[len].y=y;a[len].next=last[x];last[x]=len;}
int n,fa[110000],tot[110000],dep[110000],son[110000];
void pre_tree_node(int x) {
tot[x]=1;son[x]=0;
for(int k=last[x];k;k=a[k].next) {
int y=a[k].y;
if(y!=fa[x]) {
fa[y]=x;dep[y]=dep[x]+1;pre_tree_node(y);
tot[x]+=tot[y];if(tot[son[x]]y])son[x]=y;
}
}
}
int z,ys[110000],top[110000];
void pre_tree_edge(int x,int tp) {
ys[x]=++z;top[x]=tp;
if(son[x]!=0)pre_tree_edge(son[x],tp);
for(int k=last[x];k;k=a[k].next) {
int y=a[k].y;
if(y!=fa[x]&&y!=son[x]) pre_tree_edge(y,y);
}
}
struct trnode {int lc,rc,c,mx;}tr[5100000];int trlen,rt[210000];
void change(int &now,int l,int r,int x,int k) {
if(now==0)now=++trlen;
if(l==r){tr[now].c=tr[now].mx=k;return ;}
int mid=(l+r)/2;
if(x<=mid)change(tr[now].lc,l,mid,x,k);
else change(tr[now].rc,mid+1,r,x,k);
tr[now].c=tr[tr[now].lc].c+tr[tr[now].rc].c;
tr[now].mx=max(tr[tr[now].lc].mx,tr[tr[now].rc].mx);
}
int find_sum(int now,int l,int r,int x,int y) {
if(now==0)return 0;if(l==x&&r==y)return tr[now].c;
int mid=(l+r)/2;
if(y<=mid)return find_sum(tr[now].lc,l,mid,x,y);
else if(x>mid)return find_sum(tr[now].rc,mid+1,r,x,y);
else return find_sum(tr[now].lc,l,mid,x,mid)+find_sum(tr[now].rc,mid+1,r,mid+1,y);
}
int find_max(int now,int l,int r,int x,int y) {
if(now==0)return 0;if(l==x&&r==y)return tr[now].mx;
int mid=(l+r)/2;
if(y<=mid)return find_max(tr[now].lc,l,mid,x,y);
else if(x>mid)return find_max(tr[now].rc,mid+1,r,x,y);
else return max(find_max(tr[now].lc,l,mid,x,mid),find_max(tr[now].rc,mid+1,r,mid+1,y));
}
int solve_sum(int x,int y,int c) {
int tx=top[x],ty=top[y],ans=0;
while(tx!=ty) {
if(dep[tx]>dep[ty]) {swap(tx,ty);swap(x,y);}
ans+=find_sum(rt[c],1,n,ys[ty],ys[y]);y=fa[ty];ty=top[y];
}if(dep[x]>dep[y]) swap(x,y);
ans+=find_sum(rt[c],1,n,ys[x],ys[y]);return ans;
}
int solve_max(int x,int y,int c) {
int tx=top[x],ty=top[y],ans=0;
while(tx!=ty) {
if(dep[tx]>dep[ty]) {swap(tx,ty);swap(x,y);}
ans=max(ans,find_max(rt[c],1,n,ys[ty],ys[y]));y=fa[ty];ty=top[y];
}if(dep[x]>dep[y]) swap(x,y);
return max(ans,find_max(rt[c],1,n,ys[x],ys[y]));
}
char s[5];
int jh[110000],pj[110000];
int main() {
int m;scanf("%d%d",&n,&m);len=0;memset(last,0,sizeof(last));
for(int i=1;i<=n;i++) scanf("%d%d",&pj[i],&jh[i]);
for(int i=1;iint x,y;scanf("%d%d",&x,&y);ins(x,y);ins(y,x);}
dep[1]=0;fa[1]=0;pre_tree_node(1);z=0;pre_tree_edge(1,1);trlen=0;
for(int i=1;i<=n;i++) change(rt[jh[i]],1,n,ys[i],pj[i]);
while(m--) {
int x,y;scanf("%s%d%d",s+1,&x,&y);
if(s[1]=='C') {
if(s[2]=='C') {
change(rt[jh[x]],1,n,ys[x],0);jh[x]=y;
change(rt[jh[x]],1,n,ys[x],pj[x]);
}else {pj[x]=y;change(rt[jh[x]],1,n,ys[x],pj[x]);}
}else {
if(s[2]=='S') printf("%d\n",solve_sum(x,y,jh[x]));
else printf("%d\n",solve_max(x,y,jh[x]));
}
}
return 0;
}