

#include <bits/stdc++.h>using namespace std;typedef long long LL;const int N = 100010, M = N*2;int n, m, idx;vector<int> T[N];//id[i]: 原数组每个点的编号 //nw[i]: dfs序列中第i个点的编号 int id[N], nw[N], w[N];//top[i]: i点所在重链的顶点编号//son[i]: i点的重儿子 int dep[N], sz[N], top[N], fa[N], son[N];struct node { int l, r; LL add, sum;};struct SegTree { node tr[N*4]; void inline pushup(int u) { tr[u].sum = tr[u<<1].sum+tr[u<<1|1].sum; } void inline eval(node& t, int add) { t.sum += add*(t.r-t.l+1); t.add += add; } void inline pushdown(int u) { if (tr[u].add) { eval(tr[u<<1], tr[u].add); eval(tr[u<<1|1], tr[u].add); tr[u].add = 0; } } void build(int u, int l, int r) { tr[u] = {l, r, 0, nw[r]}; if (l == r) return; int mid = l+r>>1; build(u<<1, l, mid); build(u<<1|1, mid+1, r); pushup(u); } void update(int u, int l, int r, int k) { if (l<=tr[u].l && r>=tr[u].r) { eval(tr[u], k); return; } pushdown(u); int mid = tr[u].l+tr[u].r>>1; if (l <= mid) update(u<<1, l, r, k); if (r > mid) update(u<<1|1, l, r, k); pushup(u); } LL query(int u, int l, int r) { if (l <= tr[u].l && r >= tr[u].r) return tr[u].sum; pushdown(u); int mid = tr[u].l+tr[u].r>>1; LL res = 0; if (l <= mid) res += query(u<<1, l, r); if (r > mid) res += query(u<<1|1, l, r); return res; }}ST;void dfs1(int u, int father, int depth) { dep[u] = depth, fa[u] = father, sz[u] = 1; for (int i = 0; i < T[u].size(); i++) { int j = T[u][i]; if (j == father) continue; dfs1(j, u, depth + 1); sz[u] += sz[j]; if (sz[son[u]] < sz[j]) son[u] = j; }}void dfs2(int u, int t) { //t: 当前点所在重链的顶点 id[u] = ++idx, nw[idx] = w[u], top[u] = t; if (!son[u]) return; //优先搜索重儿子 dfs2(son[u], t); for (int i = 0; i < T[u].size(); i++) { int j = T[u][i]; if (j==fa[u] || j==son[u]) continue; //搜轻儿子,轻儿子重链顶点就是本身 dfs2(j, j); }}void update_path(int u, int v, int k) { //若两个点不在同一重链中 while (top[u] != top[v]) { if (dep[top[u]] < dep[top[v]]) swap(u, v); ST.update(1, id[top[u]], id[u], k); u = fa[top[u]]; } if (dep[u] < dep[v]) swap(u, v); ST.update(1, id[v], id[u], k);}LL query_path(int u, int v) { LL res = 0; while (top[u] != top[v]) { if (dep[top[u]] < dep[top[v]]) swap(u, v); res += ST.query(1, id[top[u]], id[u]); u = fa[top[u]]; } if (dep[u] < dep[v]) swap(u, v); res += ST.query(1, id[v], id[u]); return res;}void update_tree(int u, int k) { ST.update(1, id[u], id[u]+sz[u]-1, k);}LL query_tree(int u) { return ST.query(1, id[u], id[u]+sz[u]-1);}int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &w[i]); for (int i = 0; i < n-1; i++) { int u, v; scanf("%d%d", &u, &v); T[u].push_back(v); T[v].push_back(u); } //第一遍dfs找出每个点的重儿子 dfs1(1, -1, 1); //第二遍dfs求dfs序 dfs2(1, 1); ST.build(1, 1, n); scanf("%d", &m); while (m--) { int t, u, v, k; scanf("%d%d", &t, &u); if (t == 1) { scanf("%d%d", &v, &k); update_path(u, v, k); } else if (t == 2) { scanf("%d", &k); update_tree(u, k); } else if (t == 3) { scanf("%d", &v); printf("%lld\n", query_path(u, v)); } else { printf("%lld\n", query_tree(u)); } } return 0;}