/*
Work by: Suzt_ilymics
Knowledge: 树链剖分
Time: O(nlog^2n)
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<cstdio>
#define int long long
using namespace std;
const int inf = -1000000000;
const int MAXN = 3e4+5;
int n, m;
string s;
int a[MAXN], pre[MAXN], siz[MAXN], son[MAXN], dep[MAXN], fath[MAXN], top[MAXN], dfn[MAXN];
int read(){
int s = 0, w = 1;
char ch = getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch >= '0' && ch <= '9')
s = s * 10 + ch - '0', ch = getchar();
return s * w;
}
namespace Seg{
#define lson i << 1
#define rson i << 1 | 1
struct Tree{
int sum, lazy, len, max;
}tree[MAXN << 2];
void push_up(int i){
tree[i].sum = tree[lson].sum + tree[rson].sum;
tree[i].max = max(tree[i].max, max(tree[lson].max, tree[rson].max));
return ;
}
void build(int i, int l , int r){
tree[i].lazy = 0, tree[i].len = r - l + 1;
if(l == r) {
tree[i].sum = a[pre[l]];
tree[i].max = a[pre[l]];
return ;
}
int mid = l + r >> 1;
build(lson, l, mid), build(rson, mid + 1, r);
push_up(i);
return ;
}
void add(int i, int l, int r, int L, int R, int k){
if(L <= l && r <= R) {
tree[i].sum = k;
tree[i].max = k;
return ;
}
if(l > R || r < L) return ;
int mid = (l + r) >> 1;
if(L <= mid) add(lson, l, mid, L, R, k);
if(R > mid) add(rson, mid + 1, r, L, R, k);
push_up(i);
return ;
}
int get_sum(int i, int l, int r, int L, int R){
int sum = 0;
if(L <= l && r <= R) {
return tree[i].sum;
}
if(l > R || r < L) return 0;
int mid = (l + r) >> 1;
if(mid >= L) sum += get_sum(lson, l, mid, L, R);
if(mid < R) sum += get_sum(rson, mid + 1, r, L, R);
return sum;
}
int get_max(int i, int l, int r, int L, int R){
int maxm = inf;
if(L <= l && r <= R){
return tree[i].max;
}
if(l > R || r < L) return inf;
int mid = (l + r) >> 1;
if(mid >= L) maxm = max (maxm, get_max(lson, l, mid, L, R));
if(mid < R) maxm = max (maxm, get_max(rson, mid + 1, r, L, R));
return maxm;
}
}
namespace Cut{
int num_edge = 0, cnt = 0, head[MAXN << 1] = {0};
struct edge{
int nxt, to, from;
}e[MAXN << 1];
void add(int from, int to){
e[++num_edge].to = to;
e[num_edge].from = from;
e[num_edge].nxt = head[from];
head[from] = num_edge;
}
void dfs(int x, int fa){//
siz[x] = 1, fath[x] = fa, dep[x] = dep[fa] + 1;
for(int i = head[x]; i; i = e[i].nxt){
int v = e[i].to;
if(v == fa) continue;
dfs(v, x);
siz[x] += siz[v];
if(siz[son[x]] < siz[v]) son[x] = v;
}
}
void dfs2(int x, int tp){
top[x] = tp, dfn[x] = ++cnt, pre[cnt] = x;
if(son[x]) dfs2(son[x], tp);
for(int i = head[x]; i; i = e[i].nxt){
int v = e[i].to;
if(v == fath[x] || son[x] == v) continue;
dfs2(v, v);
}
}
int ask_sum(int x, int y){
int ans = 0;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
ans += Seg::get_sum(1, 1, n, dfn[top[x]], dfn[x]);
x = fath[top[x]];
}
if(dfn[x] > dfn[y]) swap(x, y);
ans += Seg::get_sum(1, 1, n, dfn[x], dfn[y]);
return ans;
}
int ask_max(int x, int y){
int maxm = inf;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
maxm = max (maxm, Seg::get_max(1, 1, n, dfn[top[x]], dfn[x]));
x = fath[top[x]];
}
if(dfn[x] > dfn[y]) swap(x, y);
maxm = max (maxm, Seg::get_max(1, 1, n, dfn[x], dfn[y]));
return maxm;
}
}
signed main()
{
n = read();
for(int i = 1, u, v; i <= n - 1; ++i) {
u = read(), v = read();
Cut::add(u, v), Cut::add(v, u);
}
for(int i = 1; i <= n; ++i) a[i] = read();
Cut::dfs(1,0), Cut::dfs2(1, 1), Seg::build(1, 1, n);
m = read();
for(int i = 1, x, y, k; i <= m; ++i){
cin>>s;
if(s[1] == 'M'){//Qmax
x = read(), y = read();
if(x > y) swap(x, y);
printf("%lld\n", Cut::ask_max(x, y));
}
else if(s[1] == 'H'){//Change
x = read(), k = read();
Seg::add(1, 1, n, dfn[x], dfn[x], k);
}
else if(s[1] == 'S'){//Qsum
x = read(), y = read();
if(x > y) swap(x, y);
printf("%lld\n", Cut::ask_sum(x, y));
}
}
return 0;
}