Problem

Description

S国有N个城市,编号从1到N。城市间用N-1条双向道路连接,满足
从一个城市出发可以到达其它所有城市。每个城市信仰不同的宗教,如飞天面条神教、隐形独角兽教、绝地教都是常见的信仰。为了方便,我们用不同的正整数代表各种宗教, S国的居民常常旅行。旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿。当然旅程的终点也是信仰与他相同的城市。S国政府为每个城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值。
在S国的历史上常会发生以下几种事件:
”CC x c”:城市x的居民全体改信了c教;
”CW x w”:城市x的评级调整为w;
”QS x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过的城市的评级总和;
”QM x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过
的城市的评级最大值。
由于年代久远,旅行者记下的数字已经遗失了,但记录开始之前每座城市的信仰与评级,还有事件记录本身是完好的。请根据这些信息,还原旅行者记下的数字。 为了方便,我们认为事件之间的间隔足够长,以致在任意一次旅行中,所有城市的评级和信仰保持不变。

Input

输入的第一行包含整数N,Q依次表示城市数和事件数。
接下来N行,第i+l行两个整数Wi,Ci依次表示记录开始之前,城市i的
评级和信仰。
接下来N-1行每行两个整数x,y表示一条双向道路。
接下来Q行,每行一个操作,格式如上所述。

Output

对每个QS和QM事件,输出一行,表示旅行者记下的数字。

Sample Input

5 6
3 1
2 3
1 2
3 3
5 1
1 2
1 3
3 4
3 5
QS 1 5
CC 3 1
QS 1 5
CW 3 3
QS 1 5
QM 2 4

Sample Output

8
9
11
3

HINT

N,Q < =10^5,C < =10^5

数据保证对所有QS和QM事件,起点和终点城市的信仰相同;在任意时
刻,城市的评级总是不大于10^4的正整数,且宗教值不大于C。

Solution

Analysis

宗教不是很多,直接全上线段树就行

Attention

Code

//Code by Enderturtle
#include<bits/stdc++.h>
#define rep(i,a,b) for(register int i=a;i<=b;++i)
#define repe(i,a) for(register int i=head[a];i;i=e[i].nxt)
#define il inline
#define pii pair<int,int>
#define debug cerr<<"OK Here"<<endl;
typedef long long ll;
using namespace std;
il void filejudge(){
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
}
il int read(){
    int x=0;bool f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-') f=0;ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return f?x:-x;
}
/*----- head end -----*/
const int N=100010;
const int M=10000010;
struct Edge{
    int v,nxt;
} e[N<<1];int head[N],tot;
il void add_edge(int u,int v){
    e[++tot]=(Edge){v,head[u]};
    head[u]=tot;
}
/*--------------------*/
int n,m;
int w[N],col[N];
/*--------------------*/
int sz[N],son[N],fa[N],top[N],dep[N];
int in[N],dfs_clock;
il void dfs1(int u,int f){
    dep[u]=dep[f]+1;sz[u]=1;fa[u]=f;
    repe(i,u){
        int v=e[i].v;
        if(v==f) continue;
        dfs1(v,u);
        sz[u]+=sz[v];
        if(sz[v]>sz[son[u]]) son[u]=v;
    }
}
il void dfs2(int u,int topf){
    top[u]=topf;in[u]=++dfs_clock;
    if(!son[u]) return;
    dfs2(son[u],topf);
    repe(i,u){
        int v=e[i].v;
        if(v==fa[u] || v==son[u]) continue;
        dfs2(v,v);
    }
}
il int lca(int u,int v){
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        u=fa[top[u]];
    }
    return dep[u]>dep[v]?v:u;
}
/*--------------------*/
int ls[M],rs[M],mx[M],sum[M],cnt;
int root[N];
il void up(int o){
    mx[o]=max(mx[ls[o]],mx[rs[o]]);
    sum[o]=sum[ls[o]]+sum[rs[o]];
}
il void modify(int &o,int x,int L,int R,int c){
    if(!o) o=++cnt;
    if(L==R){
        mx[o]=sum[o]=c;
        return;
    }
    int mid=(L+R)>>1;
    if(x<=mid) modify(ls[o],x,L,mid,c);
    else modify(rs[o],x,mid+1,R,c);
    up(o);
}
il int query_sum(int o,int l,int r,int L,int R){
    if(!o) return 0;
    if(L==l && R==r) return sum[o];
    int mid=(L+R)>>1,res=0;
    if(l<=mid) res=query_sum(ls[o],l,min(r,mid),L,mid);
    if(r>mid) res+=query_sum(rs[o],max(l,mid+1),r,mid+1,R);
    return res;
}
il int query_max(int o,int l,int r,int L,int R){
    if(!o) return 0;
    if(L==l && R==r) return mx[o];
    int mid=(L+R)>>1,res=0;
    if(l<=mid) res=query_max(ls[o],l,min(r,mid),L,mid);
    if(r>mid) res=max(res,query_max(rs[o],max(l,mid+1),r,mid+1,R));
    return res;
}
/*--------------*/
il int solve_sum(int x,int y,int c){
    int res=0;
    while(top[x]!=top[y]){
        res+=query_sum(root[c],in[top[x]],in[x],1,n);
        x=fa[top[x]];
    }
    res+=query_sum(root[c],in[y],in[x],1,n);
    return res;
}
il int solve_max(int x,int y,int c){
    int res=0;
    while(top[x]!=top[y]){
        res=max(res,query_max(root[c],in[top[x]],in[x],1,n));
        x=fa[top[x]];
    }
    res=max(res,query_max(root[c],in[y],in[x],1,n));
    return res;
}
int main(){
    n=read();m=read();
    rep(i,1,n) w[i]=read(),col[i]=read();
    rep(i,2,n){
        int u=read(),v=read();
        add_edge(u,v);
        add_edge(v,u);
    }
    dfs1(1,1);
    dfs2(1,1);
    rep(i,1,n) modify(root[col[i]],in[i],1,n,w[i]);
    while(m--){
        char opt[3];scanf("%s",opt);
        if(opt[0]=='C' && opt[1]=='C'){
            int x=read(),c=read();
            modify(root[col[x]],in[x],1,n,0);
            col[x]=c;
            modify(root[col[x]],in[x],1,n,w[x]);
        }else if(opt[0]=='C' && opt[1]=='W'){
            int x=read(),c=read();
            modify(root[col[x]],in[x],1,n,c);
            w[x]=c;
        }else if(opt[0]=='Q' && opt[1]=='S'){
            int x=read(),y=read();
            int c=lca(x,y);
            printf("%d\n",solve_sum(x,c,col[y])+solve_sum(y,c,col[y])-((col[c]==col[y])?w[c]:0));
        }else if(opt[0]=='Q' && opt[1]=='M'){
            int x=read(),y=read();
            int c=lca(x,y);
            printf("%d\n",max(solve_max(x,c,col[y]),solve_max(y,c,col[y])));
        }
    }
    return 0;
}

一个好奇的人