//树链剖分,线段树维护
#include <iostream>
#include <cstdio>
#define maxn 300500
#define INF 0x3f3f3f3f
using namespace std;
int n,m;
int head[maxn],cnt;
int dep[maxn],son[maxn],siz[maxn],fa[maxn];
int top[maxn],seg[maxn],rnk[maxn],tot;
int maxx[maxn],sum[maxn];
int a[maxn];
char ch;
struct EDGE
{
int next,to;
}edge[maxn];
void add(int u,int v)
{
edge[++cnt].next=head[u];
edge[cnt].to=v;
head[u]=cnt;
}
void dfs1(int root)
{
son[root]=0;
siz[root]=1;
for(int i=head[root];i;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa[root])continue;
dep[v]=dep[root]+1;
fa[v]=root;
dfs1(v);
if(siz[son[root]]<siz[v])son[root]=v;
siz[root]+=siz[v];
}
}
void dfs2(int root,int tp)
{
top[root]=tp;seg[root]=++tot;rnk[tot]=root;
if(son[root])dfs2(son[root],tp);
for(int i=head[root];i;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa[root]||v==son[root])continue;
dfs2(v,v);
}
}
void build(int k,int l,int r)
{
if(l==r)
{
maxx[k]=sum[k]=a[rnk[l]];
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
sum[k]=sum[k<<1]+sum[k<<1|1];
maxx[k]=max(maxx[k<<1],maxx[k<<1|1]);
}
void update(int k,int l,int r,int x,int v)
{
if(l==r)
{
maxx[k]=sum[k]=v;
return;
}
int mid=(l+r)>>1;
if(x<=mid)update(k<<1,l,mid,x,v);
else update(k<<1|1,mid+1,r,x,v);
sum[k]=sum[k<<1]+sum[k<<1|1];
maxx[k]=max(maxx[k<<1],maxx[k<<1|1]);
}
int querysum(int k,int l,int r,int x,int y)
{
if(x<=l&&y>=r)
{
return sum[k];
}
int mid=(l+r)>>1;
int res=0;
if(x<=mid)res+=querysum(k<<1,l,mid,x,y);
if(y>mid)res+=querysum(k<<1|1,mid+1,r,x,y);
return res;
}
int querymax(int k,int l,int r,int x,int y)
{
if(x<=l&&y>=r)
{
return maxx[k];
}
if(y<l||x>r)return -INF;
int mid=(l+r)>>1;
return max(querymax(k<<1,l,mid,x,y),querymax(k<<1|1,mid+1,r,x,y));
}
int query_Max_tree(int k,int l,int r,int u,int v)
{
int fu=top[u],fv=top[v];
int ans=-INF;
while(fu!=fv)
{
if(dep[fu]<dep[fv])
{
swap(fu,fv);
swap(u,v);
}
ans=max(ans,querymax(1,1,n,seg[fu],seg[u]));
u=fa[fu];
fu=top[u];
}
if(dep[u]<dep[v])swap(u,v);
ans=max(ans,querymax(1,1,n,seg[v],seg[u]));
return ans;
}
int query_Sum_tree(int k,int l,int r,int u,int v)
{
int fu=top[u],fv=top[v];
int ans=0;
while(fu!=fv)
{
if(dep[fu]<dep[fv])
{
swap(fu,fv);
swap(u,v);
}
ans+=querysum(1,1,n,seg[fu],seg[u]);
u=fa[fu];
fu=top[u];
}
if(dep[u]<dep[v])swap(u,v);
ans+=querysum(1,1,n,seg[v],seg[u]);
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n-1;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
dep[1]=1;dfs1(1);dfs2(1,1);
build(1,1,n);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
char op[10];
int u,v;
scanf("%s%d%d",op,&u,&v);
if(op[0]=='C')update(1,1,n,seg[u],v);
else if(op[1]=='M')printf("%d\n",query_Max_tree(1,1,n,u,v));
else printf("%d\n",query_Sum_tree(1,1,n,u,v));
}
//ch=getchar();
return 0;
}