#include<bits/stdc++.h>
using namespace std;
#define int long long
struct Node{
int nex,to;
}edge[200001];
int heads[200001],num;
inline void add(int u,int v)
{
++num;
edge[num].nex=heads[u];
edge[num].to=v;
heads[u]=num;
}
int n,m;
int fa[200001],deep[200001],totree[200001],son[200001];
int dfs1(int now,int f)
{
fa[now]=f;
deep[now]=deep[f]+1;
totree[now]=1;
int maxson=-1;
for(int i=heads[now];i!=0;i=edge[i].nex)
{
if(edge[i].to==f)continue;
totree[now]+=dfs1(edge[i].to,now);
if(totree[edge[i].to]>maxson)maxson=totree[edge[i].to],son[now]=edge[i].to;
}
return totree[now];
}
int top[200001],idx[200001],cnt,a[200001],b[200001];
void dfs2(int now,int topf)
{
idx[now]=++cnt;
top[now]=topf;
a[cnt]=b[now];
if(!son[now])return ;
dfs2(son[now],topf);
for(int i=heads[now];i!=0;i=edge[i].nex)
if(!idx[edge[i].to])dfs2(edge[i].to,edge[i].to);
}
int tree[400001],tag[400001],tree_max[400001];
void build(int node,int start,int end)
{
if(start==end){tree[node]=a[start];tree_max[node]=a[start];return ;}
int mid=(start+end)/2,left_node=2*node,right_node=2*node+1;
build(left_node,start,mid);build(right_node,mid+1,end);
tree[node]=tree[left_node]+tree[right_node];
tree_max[node]=max(tree[left_node],tree[right_node]);
}
void update(int newl,int newr,int l,int r,int node,int val)
{
if(newl<=l&&r<=newr){tree[node]=val;tree_max[node]=val;return ;}
int mid=(l+r)/2,left_node=2*node,right_node=2*node+1;
if(newl<=mid)update(newl,newr,l,mid,left_node,val);
if(newr>mid) update(newl,newr,mid+1,r,right_node,val);
tree[node]=tree[left_node]+tree[right_node];
tree_max[node]=max(tree[left_node],tree[right_node]);
}
int query(int query_left,int query_right,int l,int r,int node)
{
if(query_left<=l&&r<=query_right)return tree[node];
int mid=(l+r)/2,left_node=2*node,right_node=2*node+1,res=0;
if(query_left<=mid)res+=query(query_left,query_right,l,mid,left_node);
if(query_right>mid)res+=query(query_left,query_right,mid+1,r,right_node);
return res;
}
int query_max(int query_left,int query_right,int l,int r,int node)
{
if(query_left<=l&&r<=query_right)return tree_max[node];
int mid=(l+r)/2,left_node=2*node,right_node=2*node+1,res1,res2;
if(query_left<=mid)res1=query_max(query_left,query_right,l,mid,left_node);
if(query_right>mid)res2=query_max(query_left,query_right,mid+1,r,right_node);
return max(res1,res2);
}
void TreeAdd(int x,int y,int val)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])swap(x,y);
update(idx[top[x]],idx[x],1,n,1,val);
x=fa[top[x]];
}
if(deep[x]>deep[y])swap(x,y);
update(idx[x],idx[y],1,n,1,val);
}
void TreeSum(int x,int y)
{
int res=0;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])swap(x,y);
res+=query(idx[top[x]],idx[x],1,n,1);
x=fa[top[x]];
}
if(deep[x]>deep[y])swap(x,y);
res+=query(idx[x],idx[y],1,n,1);
cout<<res<<endl;
}
void TreeMax(int x,int y)
{
int res=0;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])swap(x,y);
res=max(res,query_max(idx[top[x]],idx[x],1,n,1));
x=fa[top[x]];
}
if(deep[x]>deep[y])swap(x,y);
res=max(res,query_max(idx[x],idx[y],1,n,1));
cout<<res<<endl;
}
signed main()
{
int bol,x,y,z;
scanf("%lld",&n);
for(int i=1;i<n;++i)scanf("%lld%lld",&x,&y),add(x,y),add(y,x);
for(int i=1;i<=n;++i)scanf("%lld",&b[i]);
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
scanf("%lld",&m);
while(m--)
{
char ch[12];
cin>>ch;
if(ch[1]=='H'){scanf("%lld%lld",&x,&y);TreeAdd(x,x,y);continue;}
if(ch[1]=='M'){scanf("%lld%lld",&x,&y);TreeMax(x,y);continue;}
if(ch[1]=='S'){scanf("%lld%lld",&x,&y);TreeSum(x,y);continue;}
}
return 0;
}