#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 5;
int n, u, v, q, tmp;
int w[N], dfn[N], _dfn[N], fa[N], dep[N], sz[N], son[N], top[N];
char s[26];
vector<int> edge[N];
struct node {
int val, l, r;
} maxtree[N << 2], sumtree[N << 2];
void dfs1(int T, int f) {
dfn[T] = ++tmp;
_dfn[tmp] = T;
sz[T] = 1;
fa[T] = f;
dep[T] = dep[f] + 1;
for (int i = 0; i < edge[T].size(); i++) {
if (edge[T][i] == f)
continue;
dfs1(edge[T][i], T);
sz[T] += sz[edge[T][i]];
if (sz[edge[T][i]] > sz[son[T]])
son[T] = edge[T][i];
}
return;
}
void dfs2(int T, int tp) {
top[T] = tp;
if (!son[T])
return;
dfs2(son[T], tp);
for (int i = 0; i < edge[T].size(); i++) {
if (edge[T][i] == fa[T] || edge[T][i] == son[T])
continue;
dfs2(edge[T][i], edge[T][i]);
}
return;
}
void build(int T, int l, int r) {
maxtree[T].l = sumtree[T].l = l;
maxtree[T].r = sumtree[T].r = r;
if (l == r) {
maxtree[T].val = sumtree[T].val = w[_dfn[l]];
return;
}
int mid = (l + r) >> 1;
build(T << 1, l, mid);
build(T << 1 | 1, mid + 1, r);
maxtree[T].val = max(maxtree[T << 1].val, maxtree[T << 1 | 1].val);
sumtree[T].val = sumtree[T << 1].val + sumtree[T << 1 | 1].val;
return;
}
int querymax(int T, int l, int r) {
if (l <= maxtree[T].l && maxtree[T].r <= r)
return maxtree[T].val;
int mid = (maxtree[T].l + maxtree[T].r) >> 1, ret = -N;
if (r <= mid)
ret = max(ret, querymax(T << 1, l, r));
if (l > mid)
ret = max(ret, querymax(T << 1 | 1, l, r));
if (l <= mid && r > mid)
ret = max(querymax(T << 1, l, r), querymax(T << 1 | 1, l, r));
return ret;
}
int querysum(int T, int l, int r) {
if (l <= sumtree[T].l && sumtree[T].r <= r)
return sumtree[T].val;
int mid = (sumtree[T].l + sumtree[T].r) >> 1, ret = 0;
if (r <= mid)
ret += querysum(T << 1, l, r);
if (l > mid)
ret += querysum(T << 1 | 1, l, r);
if (l <= mid && r > mid)
ret = querysum(T << 1, l, r) + querysum(T << 1 | 1, l, r);
return ret;
}
void change(int T) {
if (maxtree[T].l == maxtree[T].r) {
w[T] = maxtree[T].val = sumtree[T].val = v;
return;
}
int mid = (maxtree[T].l + maxtree[T].r) >> 1;
if (u <= mid)
change(T << 1);
if (u > mid)
change(T << 1 | 1);
maxtree[T].val = max(maxtree[T << 1].val, maxtree[T << 1 | 1].val);
sumtree[T].val = sumtree[T << 1].val + sumtree[T << 1 | 1].val;
return;
}
void qmax(int A, int B) {
int ans = -N;
while (top[A] != top[B]) {
if (dep[top[A]] < dep[top[B]])
swap(A, B);
ans = max(ans, querymax(1, dfn[top[A]], dfn[A]));
A = fa[top[A]];
}
if (dep[A] < dep[B])
swap(A, B);
ans = max(ans, querymax(1, dfn[B], dfn[A]));
printf("%d\n", ans);
return;
}
void qsum(int A, int B) {
int ans = 0;
while (top[A] != top[B]) {
if (dep[top[A]] < dep[top[B]])
swap(A, B);
ans += querysum(1, dfn[top[A]], dfn[A]);
A = fa[top[A]];
}
if (dep[A] < dep[B])
swap(A, B);
ans += querysum(1, dfn[B], dfn[A]);
printf("%d\n", ans);
return;
}
int main() {
scanf("%d", &n);
for (int i = 1; i < n; i++) {
scanf("%d%d", &u, &v);
edge[u].push_back(v);
edge[v].push_back(u);
}
for (int i = 1; i <= n; i++) scanf("%d", &w[i]);
dfs1(1, 0);
dfs2(1, 1);
build(1, 1, n);
scanf("%d", &q);
while (q--) {
scanf("%s%d%d", s + 1, &u, &v);
if (s[2] == 'H')
u = dfn[u], change(1);
if (s[2] == 'M')
qmax(u, v);
if (s[2] == 'S')
qsum(u, v);
}
return 0;
}