#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 30000+10;
const int INF = 0x3f3f3f3f;
struct edge {
int next,to;
}e[maxn*2];
int n,m,cnt = 0,c = 0,head[maxn];
int a[maxn],sum[maxn<<2],m_ax[maxn<<2],add[maxn<<2]; //线段树需要
int f[maxn],d[maxn],siz[maxn],son[maxn]; //dfs1
int tid[maxn],top[maxn],rk[maxn]; //dfs2 tid代表点对应的边,rk反过来
void addedge (int x,int y) {
e[++c].next = head[x];
e[c].to = y;
head[x] = c;
}
void dfs1(int u,int fa,int depth) {
f[u] = fa;
d[u] = depth;
siz[u] = 1;
for (int i = head[u]; i; i = e[i].next) {
int v = e[i].to;
if (v == fa) continue;
dfs1(v,u,depth+1);
siz[u] += siz[v];
if (siz[son[u]] < siz[v]) son[u] = v;
}
}
void dfs2(int u,int t) {
top[u] = t;
tid[u] = ++cnt;
rk[cnt] = u;
if (!son[u]) return;
dfs2(son[u],t);
for (int i = head[u]; i; i = e[i].next) {
int v = e[i].to;
if (v == son[u] || v == f[u]) continue;
dfs2(v,v);
}
}
void pushup(int rt) {
sum[rt] = sum[rt<<1]+sum[rt<<1|1];
m_ax[rt] = max(m_ax[rt<<1],m_ax[rt<<1|1]);
}
void build(int l,int r,int rt) {
if (l == r) {
sum[rt] = a[rk[l]];
m_ax[rt] = a[rk[l]];
return;
}
int mid = (l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
pushup(rt);
}
void update(int l,int r,int L,int R,int c,int rt) {
if (l <= L && R <= r) {
sum[rt] += c*(R-L+1);
m_ax[rt] += c;
add[rt] += c;
return;
}
int mid = (L+R)>>1;
if (l <= mid) update(l,r,L,mid,c,rt<<1);
if (r > mid) update(l,r,mid+1,R,c,rt<<1|1);
pushup(rt);
}
void pushdown(int rt,int ln,int rn) {
if (add[rt]) {
add[rt<<1] += add[rt];
add[rt<<1|1] += add[rt];
sum[rt<<1] += ln*add[rt];
sum[rt<<1|1] += rn*add[rt];
m_ax[rt<<1] += add[rt];
m_ax[rt<<1|1] += add[rt];
add[rt] = 0;
}
}
int query1(int l,int r,int L,int R,int rt) {
if (l <= L && R <= r) {
return sum[rt];
}
int mid = (L+R)>>1, ans = 0;
pushdown(rt,mid-L+1,R-mid);
if (l <= mid) ans += query1(l,r,L,mid,rt<<1);
if (r > mid) ans += query1(l,r,mid+1,R,rt<<1|1);
return ans;
}
int query2(int l,int r,int L,int R,int rt) {
if (l <= L && R <= r) {
return m_ax[rt];
}
int mid = (L+R)>>1, ans = -INF;
pushdown(rt,mid-L+1,R-mid);
if (l <= mid) ans = max(ans,query2(l,r,L,mid,rt<<1));
if (r > mid) ans = max(ans,query2(l,r,mid+1,R,rt<<1|1));
return ans;
}
int getsum(int x,int y) {
int ans = 0, fx = top[x], fy = top[y];
while(fx != fy) {
if (d[fx] >= d[fy]) {
ans += query1(tid[fx],tid[x],1,cnt,1);
x = f[fx];
}
else {
ans += query1(tid[fy],tid[y],1,cnt,1);
y = f[fy];
}
fx = top[x];
fy = top[y];
}
if (tid[x] < tid[y])
ans += query1(tid[x],tid[y],1,cnt,1);
else
ans += query1(tid[y],tid[x],1,cnt,1);
return ans;
}
int getmax(int x,int y) {
int ans = -INF, fx = top[x], fy = top[y];
while(fx != fy) {
if (d[fx] >= d[fy]) {
ans = max(ans,query2(tid[fx],tid[x],1,cnt,1));
x = f[fx];
}
else {
ans = max(ans,query2(tid[fy],tid[y],1,cnt,1));
y = f[fy];
}
fx = top[x];
fy = top[y];
}
if (tid[x] < tid[y])
ans = max(ans,query2(tid[x],tid[y],1,cnt,1));
else
ans = max(ans,query2(tid[y],tid[x],1,cnt,1));
return ans;
}
void change(int x,int y,int c) {
int fx = top[x], fy = top[y];
while(fx != fy) {
if (d[fx] >= d[fy]) {
update(tid[fx],tid[x],1,cnt,c,1);
x = f[fx];
}
else {
update(tid[fy],tid[y],1,cnt,c,1);
y = f[fy];
}
fx = top[x];
fy = top[y];
}
if (tid[x] < tid[y])
update(tid[x],tid[y],1,cnt,c,1);
else
update(tid[y],tid[x],1,cnt,c,1);
return;
}
int main() {
int n,l,r,q;
scanf ("%d",&n);
for (int i = 1; i <= n-1; i++) {
scanf ("%d%d",&l,&r);
addedge(l,r);
addedge(r,l);
}
for (int i = 1; i <= n; i++) scanf ("%d",&a[i]);
dfs1(1,0,1);
dfs2(1,1);
build(1,cnt,1);
scanf ("%d",&q);
char op[10];
while(q--) {
scanf ("%s%d%d",op,&l,&r);
if (op[1] == 'M') {
int ans = getmax(l,r);
printf ("%d\n",ans);
}
else if (op[1] == 'S') {
int ans = getsum(l,r);
printf ("%d\n",ans);
}
else
change(l,l,r);
}
return 0;
}