#include <bits/stdc++.h>   const int N = 1e5 + 5, M = 2e5 + 5, logN = 17 + 1;   int n, m, root, idx, a[N], f[N][logN], dfn[N], seq[N], sz[N], dep[N];   int tot, lnk[N], ter[M], nxt[M];   long long seg[N << 2], tag[N << 2];   void pushup(int rt) { seg[rt] = seg[rt << 1] + seg[rt << 1 | 1]; }   void build(int rt, int l, int r) {     if (l == r) {       seg[rt] = a[seq[l]];       return;     }     int mid = (l + r) >> 1;     build(rt << 1, l, mid);     build(rt << 1 | 1, mid + 1, r);     pushup(rt);   }   void update(int rt, int l, int r, long long k) {     seg[rt] += 1LL * (r - l + 1) * k;     tag[rt] += k;   }   void pushdown(int rt, int l, int r) {     if (!tag[rt]) return;     int mid = (l + r) >> 1;     update(rt << 1, l, mid, tag[rt]);     update(rt << 1 | 1, mid + 1, r, tag[rt]);     tag[rt] = 0;   }   void modify(int x, int y, int rt, int l, int r, int k) {     if (x <= l && r <= y) {       update(rt, l, r, k);       return;     }     pushdown(rt, l, r);     int mid = (l + r) >> 1;     if (x <= mid) modify(x, y, rt << 1, l, mid, k);     if (mid < y) modify(x, y, rt << 1 | 1, mid + 1, r, k);     pushup(rt);   }   long long query(int x, int y, int rt, int l, int r) {     if (x <= l && r <= y) return seg[rt];     pushdown(rt, l, r);     int mid = (l + r) >> 1;     long long ret = 0;     if (x <= mid) ret += query(x, y, rt << 1, l, mid);     if (mid < y) ret += query(x, y, rt << 1 | 1, mid + 1, r);     return ret;   }   void add(int u, int v) { ter[++tot] = v, nxt[tot] = lnk[u], lnk[u] = tot; }   void dfs(int u, int fa) {     dep[u] = dep[fa] + 1, f[u][0] = fa, dfn[u] = ++idx, seq[idx] = u, sz[u] = 1;     for (int i = 1; (1 << i) <= dep[u]; ++i) f[u][i] = f[f[u][i - 1]][i - 1];     for (int i = lnk[u]; i; i = nxt[i]) {       int v = ter[i];       if (v == fa) continue;       dfs(v, u), sz[u] += sz[v];     }   }   int lca(int u, int v) {     if (dep[u] > dep[v]) u ^= v ^= u ^= v;     for (int i = 17; ~i; --i)       if (dep[f[v][i]] >= dep[u]) v = f[v][i];     if (u == v) return u;     for (int i = 17; ~i; --i)       if (f[u][i] ^ f[v][i]) u = f[u][i], v = f[v][i];     return f[u][0];   }   int getlca(int u, int v, int p) {     int x = lca(u, v), y = lca(u, p), z = lca(v, p);     if (dep[y] > dep[x]) x = y;     if (dep[z] > dep[x]) x = z;     return x;   }   int jump(int u, int d) {     for (int i = 17; ~i; --i)       if (d & (1 << i)) u = f[u][i];     return u;   }   void treeModify(int u, int k) {     int l = dfn[u], r = dfn[u] + sz[u] - 1;     if (u == root)       modify(1, n, 1, 1, n, k);     else if (dfn[root] < l || dfn[root] > r)       modify(l, r, 1, 1, n, k);     else {       int son = jump(root, dep[root] - dep[u] - 1);       modify(1, n, 1, 1, n, k),           modify(dfn[son], dfn[son] + sz[son] - 1, 1, 1, n, -k);     }   }   long long treeQuery(int u) {     int l = dfn[u], r = dfn[u] + sz[u] - 1;     if (u == root)       return query(1, n, 1, 1, n);     else if (dfn[root] < l || dfn[root] > r)       return query(l, r, 1, 1, n);     else {       int son = jump(root, dep[root] - dep[u] - 1);       return query(1, n, 1, 1, n) -              query(dfn[son], dfn[son] + sz[son] - 1, 1, 1, n);     }   }   int main() {     scanf( %d%d , &n, &m);     for (int i = 1; i <= n; ++i) scanf( %d , &a[i]);     for (int i = 1; i < n; ++i) {       int u, v;       scanf( %d%d , &u, &v);       add(u, v), add(v, u);     }     dfs(1, 0);     build(1, 1, n);     root = 1;     while (m--) {       int opt;       scanf( %d , &opt);       if (opt == 1) {         scanf( %d , &root);       } else if (opt == 2) {         int u, v, x;         scanf( %d%d%d , &u, &v, &x);         treeModify(getlca(u, v, root), x);       } else {         int x;         scanf( %d , &x);         printf( %lld n , treeQuery(x));       }     }     return 0;   }