#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<climits>
#define yes puts("YES");
#define no puts("NO");
using namespace std;
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0' or ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0' and ch<='9')s=s*10+(ch-'0'),ch=getchar();
return s*w;
}
inline int Max(int x,int y){return x>y?x:y;}
inline int Min(int x,int y){return x<y?x:y;}
inline void Swap(int&x,int&y){x^=y;y^=x;x^=y;}
const int MAXN(3e4+10);
int n,m,a[MAXN];
struct E{int to,nxt;};
E edge[MAXN<<1];
int head[MAXN],tot;
inline void add_edge(int u,int v)
{
edge[++tot].nxt=head[u];
head[u]=tot;
edge[tot].to=v;
return;
}
int rk[MAXN],idx[MAXN],top[MAXN],siz[MAXN],par[MAXN],dep[MAXN],son[MAXN],cnt;
struct Segment
{
int tree[MAXN*4],maxx[MAXN];
inline int lc(int p){return p<<1;}
inline int rc(int p){return p<<1|1;}
inline void push_up(int u)
{
tree[u]=tree[lc(u)]+tree[rc(u)];
maxx[u]=Max(maxx[lc(u)],maxx[rc(u)]);
return;
}
inline void build(int u,int l,int r)
{
if(l==r)
{
tree[u]=maxx[u]=rk[a[l]];
return;
}
int mid=(l+r)>>1;
build(lc(u),l,mid);
build(rc(u),mid+1,r);
push_up(u);
return;
}
inline void update(int u,int l,int r,int p,int k)
{
if(l==p&&r==p)
{
tree[u]=maxx[u]=p;
return;
}
int mid=(l+r)>>1;
if(p<=mid) update(lc(u),l,mid,p,k);
else update(rc(u),mid+1,r,p,k);
push_up(u);
return;
}
inline int qsum(int u,int l,int r,int ln,int rn)
{
int res(0);
if(ln<=l&&r<=rn) return tree[u];
int mid=(l+r)>>1;
if(ln<=mid) res+=qsum(lc(u),l,mid,ln,rn);
if(rn>mid) res+=qsum(rc(u),mid+1,r,ln,rn);
return res;
}
inline int qmax(int u,int l,int r,int ln,int rn)
{
printf("u:%d %d %d %d %d\n",u,l,r,ln,rn);
getchar();
int res(INT_MIN);
if(ln<=l&&r<=rn) return maxx[u];
int mid=(l+r)>>1;
if(ln<=mid) res=Max(res,qmax(lc(u),l,mid,ln,rn));
if(rn>mid) res=Max(res,qmax(rc(u),mid+1,r,ln,rn));
return res;
}
};
Segment seg;
inline void dfs1(int u,int fa,int depth)
{
dep[u]=depth+1;
siz[u]=1;
par[u]=fa;
for(register int i=head[u];i;i=edge[i].nxt)
{
E e=edge[i];
if(e.to==fa) continue;
dfs1(e.to,u,depth+1);
siz[u]+=siz[e.to];
if(siz[e.to]>siz[son[u]]) son[u]=e.to;
}
return;
}
inline void dfs2(int u,int topf)
{
top[u]=topf;
idx[u]=++cnt;
rk[cnt]=u;
if(son[u]) dfs2(son[u],topf);
for(register int i=head[u];i;i=edge[i].nxt)
{
E e=edge[i];
if(e.to==par[u]||e.to==son[u]) continue;
dfs2(e.to,e.to);
}
return;
}
inline void modify(int u,int k)
{
seg.update(1,1,n,idx[u],k);
return;
}
inline int sum(int x,int y)
{
int fx=top[x],fy=top[y],res(0);
while(fx!=fy)
{
if(dep[x]<dep[y]) Swap(x,y);
res+=seg.qsum(1,1,n,idx[fx],idx[x]);
x=par[fx];
fx=top[x];
}
if(dep[x]>dep[y]) Swap(x,y);
res+=seg.qsum(1,1,n,idx[x],idx[y]);
return res;
}
inline int Maxv(int x,int y)
{
int fx=top[x],fy=top[y],res(INT_MIN);
while(fx!=fy)
{
if(dep[x]<dep[y]) Swap(x,y);
res=Max(res,seg.qmax(1,1,n,idx[fx],idx[x]));
x=par[fx];
fx=top[x];
}
if(dep[x]>dep[y]) Swap(x,y);
res=Max(res,seg.qmax(1,1,n,idx[x],idx[y]));
return res;
}
char opt[10];
int main()
{
n=read();
for(register int i=1;i<n;i++)
{
int u=read(),v=read();
add_edge(u,v);
add_edge(v,u);
}
for(register int i=1;i<=n;i++) a[i]=read();
dfs1(1,0,1);
dfs2(1,1);
seg.build(1,1,n);
m=read();
yes
while(m--)
{
scanf("%s",opt);
if(opt[0]=='C')
{
int u=read(),k=read();
modify(u,k);
}
else if(opt[1]=='M')
{
int u=read(),v=read();
printf("%d\n",Maxv(u,v));
}
else
{
int u=read(),v=read();
printf("%d\n",sum(u,v));
}
}
return 0;
}