#include <bits/stdc++.h>
using namespace std;
#define N 100010
int n,q;
string op;
int u,v;
int w[N],c[N];
int son[N],fa[N],size[N],dep[N];
int id[N],rev[N],top[N],cnt=0,num=0;
struct list{
int to,nxt,head;
}G[N<<1];
int tot=0;
struct node{
int sum,mmax,l,r;
}tree[N<<4];
int root[N];
void add(int a,int b){
G[++tot].to=b;
G[tot].nxt=G[a].head;
G[a].head=tot;
}
void dfs1(int u,int ffa){
size[u]=1;
dep[u]=dep[ffa]+1;
fa[u]=ffa;
for(int i=G[u].head;i;i=G[i].nxt){
int v=G[i].to;
if(v==ffa) continue;
dfs1(v,u);
size[u]+=size[v];
if(size[v]>size[son[u]]) son[u]=v;
}
}
void dfs2(int u,int t){
top[u]=t;
id[u]=++cnt;
rev[cnt]=u;
if(!son[u]) return;
dfs2(son[u],t);
for(int i=G[u].head;i;i=G[i].nxt){
int v=G[i].to;
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
void pushup(int u){
tree[u].sum=tree[tree[u].l].sum+tree[tree[u].r].sum;
tree[u].mmax=max(tree[tree[u].l].mmax,tree[tree[u].r].mmax);
}
void update(int &u,int l,int r,int pos,int x){
if(!u) u=++num;
if(l>=pos&&r<=pos){
tree[u].sum=x;
tree[u].mmax=max(tree[u].mmax,x);
return;
}
int mid=l+r>>1;
if(mid>=pos) update(tree[u].l,l,mid,pos,x);
else update(tree[u].r,mid+1,r,pos,x);
pushup(u);
}
void update_zj(int pos,int x){
update(root[c[x]],1,n,id[pos],w[pos]);
update(root[c[pos]],1,n,id[pos],0);
c[pos]=x;
}
void update_pj(int pos,int x){
update(root[c[pos]],1,n,id[pos],x);
w[pos]=x;
}
int query_sum_(int u,int l,int r,int nl,int nr){
if(l>=nl&&r<=nr) return tree[u].sum;
int mid=l+r>>1,sum=0;
if(mid>=nl) sum+=query_sum_(tree[u].l,l,mid,nl,nr);
if(mid<nr) sum+=query_sum_(tree[u].r,mid+1,r,nl,nr);
return sum;
}
int query_sum(int u,int v,int zj){
int ans=0;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
ans+=query_sum_(root[zj],1,n,id[top[u]],id[u]);
u=fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
ans+=query_sum_(root[zj],1,n,id[u],id[v]);
return ans;
}
int query_max_(int u,int l,int r,int nl,int nr){
if(l>=nl&&r<=nr) return tree[u].mmax;
int mid=l+r>>1,sum=0;
if(mid>=nl) sum=max(sum,query_max_(tree[u].l,l,mid,nl,nr));
if(mid<nr) sum=max(sum,query_max_(tree[u].r,mid+1,r,nl,nr));
return sum;
}
int query_max(int u,int v,int zj){
int ans=0;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
ans=max(ans,query_max_(root[zj],1,n,id[top[u]],id[u]));
u=fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
ans=max(ans,query_max_(root[zj],1,n,id[u],id[v]));
return ans;
}
int main(){
scanf("%d %d",&n,&q);
for(int i=1;i<=n;i++){
scanf("%d %d",&w[i],&c[i]);
}
for(int i=1,u,v;i<n;i++){
scanf("%d %d",&u,&v);
add(u,v),add(v,u);
}
dfs1(1,0),dfs2(1,1);
for(int i=1;i<=n;i++){
update(root[c[i]],1,n,id[i],w[i]);
}
while(q--){
cin>>op;
scanf("%d %d",&u,&v);
if(op=="CC") update_zj(u,v);
else if(op=="CW") update_pj(u,v);
else if(op=="QS") printf("%d\n",query_sum(u,v,c[u]));
else printf("%d\n",query_max(u,v,c[u]));
}
return 0;
}