rt
#include<bits/stdc++.h>
#define int long long
#define N 100000
using namespace std;
struct Node{int f,dep,dfn,top,size,hson;Node(){f=dep=dfn=top=size=hson=0;}};
struct Node2{int l,r,v;Node2(){l=r=v=0;}};
int n,q,w[N+5]={},c[N+5]={},ux,uy,tot=0,tot1=0,tot2=0,root[N+5]={},root2[N+5]={};
vector<int>edge[N+5];
Node tree[N+5];
Node2 line1[N*40],line2[N*40];
string opt;
int newNode(int v){line1[++tot1].v=v;return tot1;}
int newNode2(int v){line2[++tot2].v=v;return tot2;}
int read(){
int f=1,g=0;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while('0'<=ch&&ch<='9'){
g=g*10+ch-'0';
ch=getchar();
}
return f*g;
}
void print(int x){
if(x<0){
putchar('-');
x*=-1;
}
if(x>9)print(x/10);
putchar(x%10+'0');
return;
}
void putdown(int l,int r,int x,int v,int p){
if(l==r){
line1[p].v=v;
return;
}
int mid=(l+r)>>1;
if(x<=mid){
if(!line1[p].l)line1[p].l=newNode(v);
putdown(l,mid,x,v,line1[p].l);
}
else{
if(!line1[p].r)line1[p].r=newNode(v);
putdown(mid+1,r,x,v,line1[p].r);
}
line1[p].v=line1[line1[p].l].v+line1[line1[p].r].v;
return;
}
void putdown2(int l,int r,int x,int v,int p){
if(l==r){
line2[p].v=v;
return;
}
int mid=(l+r)>>1;
if(x<=mid){
if(!line2[p].l)line2[p].l=newNode2(v);
putdown2(l,mid,x,v,line2[p].l);
}
else{
if(!line2[p].r)line2[p].r=newNode2(v);
putdown2(mid+1,r,x,v,line2[p].r);
}
line2[p].v=max(line2[line2[p].l].v,line2[line2[p].r].v);
return;
}
int find(int s,int t,int l,int r,int p){
if(s<=l&&r<=t)return line1[p].v;
int mid=(l+r)>>1,sum=0;
if(t<=mid&&line1[p].l)sum+=find(s,t,l,mid,line1[p].l);
if(s>mid&&line1[p].r)sum+=find(s,t,mid+1,r,line1[p].r);
return sum;
}
int find2(int s,int t,int l,int r,int p){
if(s<=l&&r<=t)return line2[p].v;
int mid=(l+r)>>1,sum=0;
if(t<=mid&&line2[p].l)sum=max(sum,find2(s,t,l,mid,line2[p].l));
if(s>mid&&line2[p].r)sum=max(sum,find2(s,t,mid+1,r,line2[p].r));
return sum;
}
void build1(int x,int dep){
tree[x].dep=dep,tree[x].size=1;
for(int i:edge[x]){
if(i==tree[x].f)continue;
tree[i].f=x;
build1(i,dep+1);
tree[x].size+=tree[i].size;
if(tree[i].size>tree[tree[x].hson].size)tree[x].hson=i;
}
return;
}
void build2(int x,int top){
tree[x].dfn=++tot,tree[x].top=top;
putdown(1,n,tree[x].dfn,w[x],root[c[x]]);
putdown2(1,n,tree[x].dfn,w[x],root2[c[x]]);
if(tree[x].hson)build2(tree[x].hson,top);
for(int i:edge[x]){
if(i==tree[x].f||i==tree[x].hson)continue;
build2(i,i);
}
return;
}
int lca(int x,int y,int k){
int sum=0;
while(tree[x].top!=tree[y].top){
if(tree[tree[x].top].dep<tree[tree[y].top].dep)swap(x,y);
sum+=find(tree[tree[x].top].dfn,tree[x].dfn,1,n,root[k]);
x=tree[tree[x].top].f;
}
sum+=(tree[x].dep>tree[y].dep?find(tree[y].dfn,tree[x].dfn,1,n,root[k]):find(tree[x].dfn,tree[y].dfn,1,n,root[k]));
return sum;
}
int lca2(int x,int y,int k){
int sum=0;
while(tree[x].top!=tree[y].top){
if(tree[tree[x].top].dep<tree[tree[y].top].dep)swap(x,y);
sum=max(sum,find2(tree[tree[x].top].dfn,tree[x].dfn,1,n,root2[k]));
x=tree[tree[x].top].f;
}
sum=max(sum,(tree[x].dep>tree[y].dep?find2(tree[y].dfn,tree[x].dfn,1,n,root2[k]):find2(tree[x].dfn,tree[y].dfn,1,n,root2[k])));
return sum;
}
main(){
// freopen("P3313_2.in","r",stdin);
// freopen("c.out","w",stdout);
n=read(),q=read();
for(int i=1;i<=n;i++)w[i]=read(),c[i]=read();
for(int i=1;i<n;i++){
ux=read(),uy=read();
edge[ux].push_back(uy);
edge[uy].push_back(ux);
}
for(int i=1;i<=N;i++)root[i]=newNode(0),root2[i]=newNode2(0);
build1(1,1);
build2(1,1);
for(int i=1;i<=q;i++){
cin>>opt;
ux=read(),uy=read();
if(opt=="CC"){
putdown(1,n,tree[ux].dfn,0,root[c[ux]]);
putdown2(1,n,tree[ux].dfn,0,root2[c[ux]]);
putdown(1,n,tree[ux].dfn,w[ux],root[uy]);
putdown2(1,n,tree[ux].dfn,w[ux],root2[uy]);
c[ux]=uy;
}
else if(opt=="CW"){
putdown(1,n,tree[ux].dfn,uy,root[c[ux]]);
putdown2(1,n,tree[ux].dfn,uy,root2[c[ux]]);
w[ux]=uy;
}
else if(opt=="QS")print(lca(ux,uy,c[ux])),putchar('\n');
else print(lca2(ux,uy,c[ux])),putchar('\n');
}
return 0;
}