#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int manx=1e6+10;
const int mamx = 1e6 + 11;
const ll mod = 2123400401301379571;
const int inf = 0x3f3f3f3f;
inline int read() {
char c = getchar(); int x = 0, f = 1;
for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
}
struct node{
int v,nxt;
}e[manx << 1];
int head[manx],cnt,n,m,val[manx];
int js,size_[manx],dep[manx],fa[manx],dfsn[manx],tp[manx],hson[manx],bz[manx];
char a[manx];
inline void add(int u,int v){
e[++cnt].v = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
namespace Seg{
#define ls i<<1
#define rs i<<1|1
struct node{
int l,r;
ll sum,lazy,mxa;
}tr[manx<<2];
inline void update(int i){
tr[i].sum = tr[ls].sum + tr[rs].sum;
tr[i].mxa = max(tr[ls].mxa ,tr[rs].mxa);
}
inline void down(int i){
if(tr[i].lazy){
ll x = tr[i].lazy;
tr[ls].sum = (tr[i].r - tr[i].l + 1)*x;
tr[rs].sum = (tr[i].r - tr[i].l + 1)*x;
tr[ls].lazy = x;
tr[rs].lazy = x;// 写挂了
tr[ls].mxa = x;
tr[rs].mxa = x;
tr[i].lazy = 0;
}
}
inline void build(int i,int l,int r){
tr[i].l = l; tr[i].r = r;
if(l == r){
tr[i].sum = val[bz[l]];
tr[i].mxa = val[bz[l]];
return;
}
int mid = (l+r) >> 1;
build(ls, l, mid);
build(rs, mid+1, r);
update(i);
}
inline void tree_add(int i,int l,int r,int add){
if(tr[i].l >= l && tr[i].r <= r){
tr[i].sum += (tr[i].r - tr[i].l + 1)*add;
tr[i].lazy += add;
return;
}
int mid = (tr[i].l + tr[i].r) >> 1;
if(mid >= r) tree_add(ls,l,r,add);
else if(mid < l) tree_add(rs,l,r,add);
else tree_add(ls,l,mid,add),tree_add(rs,mid+1,r,add);
update(i);
}
inline void tree_only_add(int i,int u,int add){
if(tr[i].l == tr[i].r ){
tr[i].sum = add;
return;
}
int mid = (tr[i].l + tr[i].r ) >> 1;
if(mid >= u)tree_only_add(ls,u,add);
else tree_only_add(rs,u,add);
update(i);
}
inline ll tree_query(int i,int l,int r){
if(tr[i].l >= l && tr[i].r <= r){
return tr[i].sum ;
}
down(i);
int mid = (tr[i].l + tr[i].r ) >> 1;
if(mid >= r) return tree_query(ls, l, r) ;
else if(mid < l) return tree_query(rs, l, r) ;
update(i);
return tree_query(ls, l, mid) +
tree_query(rs, mid+1, r) ;
}
inline ll tree_max(int i,int l,int r){
if(tr[i].l >= l && tr[i].r <= r){
return tr[i].mxa ;
}
down(i);
int mid = ( tr[i].l + tr[i].r ) >> 1;
if(mid >= r) return tree_max (ls, l, r);
else if(mid < l) return tree_max (rs, l, r);
update(i);
return max( tree_max(ls,l,mid), tree_max(rs,mid+1,r) );
}
#undef ls
#undef rs
}
inline void dfs1(int u,int pre,int d){
fa[u] = pre; size_[u] = 1; dep[u] = d;
for(int i =head[u];i;i = e[i].nxt ){
int v = e[i].v ;
if(v != pre){
dfs1(v,u,d+1);//深搜得到重儿子
size_[u] += size_[v];//每个子树的大小
if( !hson[u] || size_[ hson[u] ] < size_[v] )
hson[u] = v;//没有重儿子或者当前子树大小比重儿子大,那么更新重儿子
}
}
}
inline void dfs2(int u,int top){
tp[u] = top; dfsn[u] = ++js;bz[js] = u;//得到DFSN,以便加入线段树
if(!hson[u]) return;//保证每一条重链都是在区间内连续
dfs2(hson[u],top);
for(int i = head[u];i;i = e[i].nxt){
int v = e[i].v;
if(v != hson[u] && v != fa[u]){//既不是重儿子,也不是父亲,就重新开一条重链
dfs2(v,v);
}
}
}
inline void path_all_add(int u,int v,int val){
while(tp[u] != tp[v]){
if(dep[tp[u]] < dep[tp[v]]) swap(u,v);
/*
思路做法同下
*/
Seg::tree_add(1,dfsn[tp[u]],dfsn[u],val);
u = fa[tp[u]];
}
if(dep[u] < dep[v]) swap(u,v);
Seg::tree_add(1,dfsn[u],dfsn[v],val);
}
inline ll path_query(int u,int v){
ll ans = 0;
while(tp[u] != tp[v]){//深度较深的先往上跳
if(dep[tp[u]] < dep[tp[v]])swap (u, v);//保证U永远都是上边的那一个点
ans += Seg::tree_query (1,dfsn[tp[u]],dfsn[u]);
u = fa[ tp[u] ];//当前重链已经操作完成,继续操作在这条路径上的部分重链且重链与当前重链相连
}
if(dep[u] > dep[v]) swap (u, v);
/*
两个重链循环完后会调到同一条链上,在进行特殊操作
*/
ans += Seg::tree_query (1, dfsn[u],dfsn[v]);
return ans;
}
inline ll path_max(int u,int v){
ll ans = 0;
while(tp[u] != tp[v]){
if(dep[ tp[u] ] < dep[ tp[v] ]) swap (u, v);
ll jj = Seg::tree_max (1, dfsn[tp[u]], dfsn[u]);
ans = max(jj, ans);
u = fa[ tp[u] ];
}
if(dep[u] > dep[u]) swap(u,v);
ll ooo = Seg::tree_max(1,dfsn[u],dfsn[v]);
ans = max(ooo,ans);
return ans;
}
int main(){
n = read();
for(int i = 1;i < n; i++){
int x = read(),y = read();
add(x,y);
add(y,x);
}
for(int i = 1;i <= n; i++){
val[i] = read();
}
m = read();
dfs1(1,0,1),
dfs2(1,1),
Seg::build(1,1,n);
while(m--){
cin>>a;
int x,y;
if(a[1]=='M'){
x = read(); y = read();
cout<<path_max(x,y)<<endl;
}
if(a[1]=='S'){
x = read(); y = read();
cout<<path_query(x,y)<<endl;
}
if(a[1]=='H'){
x = read(); y = read();
Seg::tree_only_add(1,x,y);
}
}
return 0;
}