#include<iostream>
#include<cstdio>
#include<string>
#include<vector>
using namespace std;
const int maxn=1e5+10;
vector<int> son[maxn];
bool ish[maxn];
int fa[maxn],depth[maxn],size[maxn],top[maxn],dfn[maxn],redfn[maxn],dfncnt=0;
int val[maxn];
int rel[maxn];
int hs[maxn],hv[maxn];
int n,m,rt=1;
vector<int> to[maxn];
int grtotr_vis[maxn];
void addedge(int u,int v)
{
to[u].push_back(v);
to[v].push_back(u);
}
void inputs()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&val[i],&rel[i]);
}
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
}
}
void graphtotree(int x,int dp)
{
grtotr_vis[x]=1;
depth[x]=dp;
size[x]=1;
for(int i=0;i<to[x].size();i++)
{
if(!grtotr_vis[to[x][i]])
{
int s=to[x][i];
fa[s]=x;
son[x].push_back(s);
graphtotree(s,dp+1);
size[x]+=size[s];
if(size[s]>hv[x])
{
ish[hs[x]]=0;
ish[s]=1;
hs[x]=s;
hv[x]=size[s];
}
}
}
}
void dfs1(int x)
{
dfn[++dfncnt]=x;
if(ish[x])
{
top[x]=top[fa[x]];
}
else
{
top[x]=x;
}
if(hs[x]!=0)
{
dfs1(hs[x]);
for(int i=0;i<son[x].size();i++)
{
if(son[x][i]!=hs[x])
{
dfs1(son[x][i]);
}
}
}
}
const int maxn2=2*maxn;
int sum_v[maxn2],max_v[maxn2],l[maxn2],r[maxn2],lc[maxn2],rc[maxn2],trcnt=3;
void changee(int p,int k,int v)
{
int tl=l[p],tr=r[p];
if(tl==k && tr==k)
{
sum_v[p]=max_v[p]=v;
return ;
}
int mid=(tl+tr)>>1;
if(k<=mid)
{
if(lc[p]==0)
{
lc[p]=++trcnt;
l[trcnt]=tl;
r[trcnt]=mid;
}
changee(lc[p],k,v);
sum_v[p]=sum_v[lc[p]];
max_v[p]=max_v[lc[p]];
if(rc[p])
{
sum_v[p]+=sum_v[rc[p]];
max_v[p]=max(max_v[p],max_v[rc[p]]);
}
}
else
{
if(rc[p]==0)
{
rc[p]=++trcnt;
l[trcnt]=mid+1;
r[trcnt]=tr;
}
changee(rc[p],k,v);
sum_v[p]=sum_v[rc[p]];
max_v[p]=max_v[rc[p]];
if(lc[p])
{
sum_v[p]+=sum_v[lc[p]];
max_v[p]=max(max_v[p],max_v[lc[p]]);
}
}
}
int query(int p,int ql,int qr,int tp)
{
if(ql>qr)
{
int t=ql;ql=qr;qr=t;
}
int tl=l[p],tr=r[p];
if(ql<=tl && tr<=qr)
{
return tp?sum_v[p]:max_v[p];
}
int mid=(tl+tr)>>1;
int ret=0;
if(ql<=mid && lc[p])
{
if(tp)
{
ret=ret+query(lc[p],ql,qr,tp);
}
else
{
ret=max(ret,query(lc[p],ql,qr,tp));
}
}
if(mid<qr && rc[p])
{
if(tp)
{
ret=ret+query(rc[p],ql,qr,tp);
}
else
{
ret=max(ret,query(rc[p],ql,qr,tp));
}
}
return ret;
}
void res()
{
for(int i=1;i<=3;i++)
{
l[i]=1;
r[i]=n;
}
for(int i=1;i<=n;i++)
{
changee(rel[i],redfn[i],val[i]);
}
}
int pathquery(int x,int y,int tp,int reli)
{
int ans=0;
while(top[x]!=top[y])
{
if(depth[top[x]]>=depth[top[y]])
{
if(tp)
{
ans=ans+query(reli,redfn[top[x]],redfn[x],tp);
}
else
{
ans=max(ans,query(reli,redfn[top[x]],redfn[x],tp));
}
x=top[x];
if(x!=rt) x=fa[x];
}
else
{
if(tp)
{
ans=ans+query(reli,redfn[top[y]],redfn[y],tp);
}
else
{
ans=max(ans,query(reli,redfn[top[y]],redfn[y],tp));
}
y=top[y];
if(y!=rt) y=fa[y];
}
}
if(tp)
{
ans=ans+query(reli,redfn[x],redfn[y],tp);
}
else
{
ans=max(ans,query(reli,redfn[x],redfn[y],tp));
}
return ans;
}
int main()
{
inputs();
graphtotree(rt,1);
dfs1(rt);
for(int i=1;i<=n;i++)
{
redfn[dfn[i]]=i;
}
res();
for(int i=1;i<=m;i++)
{
string op;
cin>>op;
if(op=="CC")
{
int x,y;
scanf("%d%d",&x,&y);
changee(rel[x],redfn[x],0);
changee(y,redfn[x],val[x]);
rel[x]=y;
}
else if(op=="CW")
{
int x,y;
scanf("%d%d",&x,&y);
changee(rel[x],redfn[x],y);
val[x]=y;
}
else if(op=="QS")
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",pathquery(x,y,1,rel[x]));
}
else if(op=="QM")
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",pathquery(x,y,0,rel[x]));
}
}
return 0;
}