rt,样例都过不去
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
inline int read() {
int w = 1, s = 0; char c;
while(!isdigit(c = getchar())) if(c == '-') w = -1;
while(isdigit(c)) s = (s << 1) + (s << 3) + (c & 15), c = getchar();
return s * w;
}
const int N = 1e6 + 5;
int head[N], cnt = 0;
struct edge { int v, nex; } e[N];
inline void add_edge(int u, int v) {
e[++ cnt].v = v; e[cnt].nex = head[u]; head[u] = cnt;
e[++ cnt].v = u; e[cnt].nex = head[v]; head[v] = cnt;
}
int n, Q, arr[N], son[N], top[N], siz[N], fa[N], dep[N], w1[N], w2[N], id[N], tot = 0;
struct SegMent { int l, r, lc, rc, ans, tag; } tr[N];
inline void dfs1(int x, int f, int dept) {
fa[x] = f; dep[x] = dept; siz[x] = 1;
for(int i = head[x]; i; i = e[i].nex) {
int v = e[i].v;
if(v == f) continue;
dfs1(v, x, dept + 1);
siz[x] += siz[v];
if(siz[v] > siz[son[x]]) son[x] = v;
}
} inline void dfs2(int x, int topf) {
top[x] = topf; id[x] = ++ tot; w2[tot] = w1[x];
if(!son[x]) return;
dfs2(son[x], topf);
for(int i = head[x]; i; i = e[i].nex) {
int v = e[i].v;
if(v == fa[x] || v == son[x]) continue;
dfs2(v, v);
}
}
#define mid ((tr[x].l + tr[x].r) >> 1)
inline void pushup(int x) { tr[x].ans = tr[tr[x].lc].ans + tr[tr[x].rc].ans; }
inline int build(int x, int l, int r) {
tr[x].l = l; tr[x].r = r; tr[x].tag = 0;
if(l == r) { tr[x].ans = w2[l]; return x; }
tr[x].lc = build(x << 1, l, mid);
tr[x].rc = build(x << 1 | 1, mid + 1, r);
pushup(x); return x;
}
inline void pushdown(int x) {
if(tr[x].tag) {
tr[tr[x].lc].tag += tr[x].tag;
tr[tr[x].rc].tag += tr[x].tag;
tr[tr[x].lc].ans += (tr[tr[x].lc].r - tr[tr[x].lc].l + 1) * tr[x].tag;
tr[tr[x].rc].ans += (tr[tr[x].rc].r - tr[tr[x].rc].l + 1) * tr[x].tag;
tr[x].tag = 0;
}
}
inline void modify(int x, int nl, int nr, int c) {
if(nl <= tr[x].l && tr[x].r <= nr) {
tr[x].tag += c;
tr[x].ans += (tr[x].r - tr[x].l + 1) * c;
return;
} pushdown(x);
if(nl <= mid) modify(tr[x].lc, nl, nr, c);
if(nr > mid) modify(tr[x].rc, nl, nr, c);
pushup(x);
}
inline int query(int x, int nl, int nr) {
if(nl <= tr[x].l && tr[x].r <= nr) return tr[x].ans;
pushdown(x); int res = 0;
if(nl <= mid) res += query(tr[x].lc, nl, nr);
if(nr > mid) res += query(tr[x].rc, nl, nr);
return res;
}
inline int P(int x, int y) {
while(top[x] != top[y]) {
if(dep[top[x]] <dep[top[y]]) swap(x, y);
if(fa[top[x]] == y) return top[x];
x = fa[top[x]];
} if(dep[x] > dep[y]) swap(x, y);
return son[x];
}
inline int LCA(int x, int y) {
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
x = fa[top[x]];
} return dep[x] < dep[y] ? x : y;
}
int rt = 1;
inline int Query(int x) {
if(x == rt) return query(1, 1, n);
int lca = LCA(x, rt);
if(lca == rt) return query(1, id[x], id[x] + siz[x] - 1);
if(lca != x) return query(1, id[x], id[x] + siz[x] - 1);
int p = P(x, rt);
return query(1, 1, n) - query(1, id[p], id[p] + siz[p] - 1);
}
inline void Change(int x, int c) {
if(x == rt) { modify(1, 1, n, c); return; }
int lca = LCA(x, rt);
if(lca == rt) { modify(1, id[x], id[x] + siz[x] - 1, c); return; }
if(lca != x) { modify(1, id[x], id[x] + siz[x] - 1, c); return; }
modify(1, 1, n, c);
int p = P(x, rt);
modify(1, id[p], id[p] + siz[p] - 1, -c);
}
int main() {
n = read(); Q = read();
for(int i = 1; i <= n; i ++ ) w1[i] = read();
for(int i = 1; i < n; i ++ ) {
int u = read(), v = read();
add_edge(u, v);
} dfs1(1, 0, 1); dfs2(1, 1); build(1, 1, n);
while(Q -- ) {
int opt = read();
if(opt == 1) {
int x = read();
rt = x;
} if(opt == 2) {
int x = read(), y = read(), v = read();
int lca = LCA(x, y);
Change(lca, v);
} if(opt == 3) {
int x = read();
printf("%d\n", Query(x));
}
}
}