












#include<iostream>
#include<algorithm>
const int sz = 3e4 + 10;
int arr[sz], n, q;
struct ST {
struct node {
int sum, max;
node operator+(const node &a) const {
return node{sum + a.sum, std::max(max, a.max)};
}
};
node tree[sz << 2];
void build(int p, int ln, int rn) {
if (ln == rn) return tree[p] = node{arr[ln], arr[ln]}, void();
int mid = ln + rn >> 1;
build(p << 1, ln, mid);
build(p << 1 | 1, mid + 1, rn);
tree[p] = tree[p << 1] + tree[p << 1 | 1];
}
void change(int p, int ln, int rn, int pos, int val) {
if (ln == rn) return tree[p] = node{val, val}, void();
int mid = ln + rn >> 1;
if (pos <= mid) change(p << 1, ln, mid, pos, val);
else change(p << 1 | 1, mid + 1, rn, pos, val);
tree[p] = tree[p << 1] + tree[p << 1 | 1];
}
int querymax(int p, int ln, int rn, int l, int r) {
if (ln >= l && rn <= r) return tree[p].max;
if (ln > r || rn < l) return -0x7fffffff;
int mid = ln + rn >> 1, res = -0x7fffffff;
res = std::max(res, querymax(p << 1, ln, mid, l, r));
res = std::max(res, querymax(p << 1 | 1, mid + 1, rn, l, r));
return res;
}
int querysum(int p, int ln, int rn, int l, int r) {
if (ln >= l && rn <= r) return tree[p].sum;
if (ln > r || rn < l) return 0;
int mid = ln + rn >> 1, res = 0;
res += querysum(p << 1, ln, mid, l, r);
res += querysum(p << 1 | 1, mid + 1, rn, l, r);
return res;
}
} st;
struct edge {
int nxt, to;
} graph[sz << 1];
int hpp, head[sz];
void addEdge(int from, int to) {
graph[++hpp] = edge{head[from], to};
head[from] = hpp;
}
int top[sz], hson[sz], ssz[sz], dfn[sz], dpp, fa[sz], dep[sz];
void buildDFS(int u, int fau) {
dep[u] = dep[fau] + 1, ssz[u] = 1, fa[u] = fau;
for (int p = head[u]; p; p = graph[p].nxt) {
int v = graph[p].to;
if (v == fau) return;
buildDFS(v, u);
ssz[u] += ssz[v];
if (ssz[v] > ssz[hson[u]]) hson[u] = v;
}
}
void chainDFS(int u, int t) {
dfn[u] = ++dpp, top[u] = t;
if (!hson[u]) return;
chainDFS(hson[u], t);
for (int p = head[u]; p; p = graph[p].nxt) {
int v = graph[p].to;
if (v == hson[u] || v == fa[u]) continue;
chainDFS(v, v);
}
}
int querymax(int u, int v) {
int res = -0x7fffffff;
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) std::swap(u, v);
res = std::max(res, st.querymax(1, 1, n, dfn[top[u]], dfn[u]));
u = fa[top[u]];
}
if (dfn[u] > dfn[v]) std::swap(u, v);
res = std::max(res, st.querymax(1, 1, n, dfn[u], dfn[v]));
return res;
}
int querysum(int u, int v) {
int res = 0;
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) std::swap(u, v);
res += st.querysum(1, 1, n, dfn[top[u]], dfn[u]);
u = fa[top[u]];
}
if (dfn[u] > dfn[v]) std::swap(u, v);
res += st.querysum(1, 1, n, dfn[u], dfn[v]);
return res;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin >> n;
for (int i = 1, u, v; i < n; i++) {
std::cin >> u >> v;
addEdge(u, v), addEdge(v, u);
}
buildDFS(1, 0);
chainDFS(1, 1);
for (int i = 1; i <= n; i++) std::cin >> arr[dfn[i]];
st.build(1, 1, n);
std::cin >> q;
while (q--) {
std::string op;
int x, y;
std::cin >> op >> x >> y;
if (op == "CHANGE") st.change(1, 1, n, dfn[x], y);
else if (op == "QMAX") std::cout << querymax(x, y) << "\n";
else std::cout << querysum(x, y) << "\n";
}
return 0;
}