#include <bits/stdc++.h>   using namespace std;   const long long N = 1e5 + 10;   long long h[N], e[2 * N], ne[2 * N], idx;   void add(long long a, long long b) { e[idx] = b, ne[idx] = h[a], h[a] = idx++; }   struct node {     long long sum, add;   };   node tr[N << 2];   long long arr[N];   long long f[N][20];   long long dep[N], fa[N], son[N], sz[N];   long long n, q;   void dfs1(long long u, long long fz) {     fa[u] = fz;     dep[u] = dep[fz] + 1;     sz[u] = 1;     f[u][0] = fz;     for (long long i = 1; i < 20; ++i) f[u][i] = f[f[u][i - 1]][i - 1];     for (long long i = h[u]; i != -1; i = ne[i]) {       long long j = e[i];       if (j == fz) continue;       dfs1(j, u);       sz[u] += sz[j];       if (sz[j] > sz[son[u]]) {         son[u] = j;       }     }   }   long long id[N], top[N], uid[N], tot;   void dfs2(long long u, long long topx) {     top[u] = topx;     id[u] = ++tot;     uid[tot] = u;     if (!son[u]) return;     dfs2(son[u], topx);     for (long long i = h[u]; i != -1; i = ne[i]) {       long long j = e[i];       if (j == fa[u] || j == son[u]) continue;       dfs2(j, j);     }   }   long long get_lca(long long a, long long b) {     while (top[a] != top[b]) {       if (dep[top[a]] > dep[top[b]])         a = fa[top[a]];       else         b = fa[top[b]];     }     return dep[a] > dep[b] ? b : a;   }   long long topC(long long x, long long c) {     for (long long i = 19; i >= 0; i--) {       if ((1 << i) <= c) {         x = f[x][i];         c -= (1 << i);       }     }     return x;   }   long long root;   void pushup(long long u) { tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum; }   void pushdown(long long l, long long r, long long u) {     if (tr[u].add) {       long long mid = l + r >> 1;       tr[u << 1].sum += (mid - l + 1) * tr[u].add;       tr[u << 1 | 1].sum += (r - mid) * tr[u].add;       tr[u << 1].add += tr[u].add;       tr[u << 1 | 1].add += tr[u].add;       tr[u].add = 0;     }   }   long long query(long long l, long long r, long long a, long long b,                   long long u) {     if (l <= a && b <= r) {       return tr[u].sum;     }     pushdown(a, b, u);     long long mid = a + b >> 1;     long long ans = 0;     if (l <= mid) ans += query(l, r, a, mid, u << 1);     if (r > mid) ans += query(l, r, mid + 1, b, u << 1 | 1);     return ans;   }   void ud(long long l, long long r, long long a, long long b, long long d,           long long u) {     if (l <= a && b <= r) {       tr[u].add += d;       tr[u].sum += (b - a + 1) * d;       return;     }     pushdown(a, b, u);     long long mid = a + b >> 1;     if (l <= mid) ud(l, r, a, mid, d, u << 1);     if (r > mid) ud(l, r, mid + 1, b, d, u << 1 | 1);     pushup(u);   }   void update(long long u, long long x) {     ud(id[u], id[u] + sz[u] - 1, 1, n, x, 1);   }   long long qry(long long u) { return query(id[u], id[u] + sz[u] - 1, 1, n, 1); }   void build(long long l, long long r, long long u) {     tr[u].add = 0;     if (l == r) {       tr[u].sum = arr[uid[l]];       return;     }     long long mid = l + r >> 1;     build(l, mid, u << 1);     build(mid + 1, r, u << 1 | 1);     pushup(u);   }   int main() {     ios::sync_with_stdio(false);     std::cin.tie(0);     memset(h, -1, sizeof h);     cin >> n >> q;     for (long long i = 1; i <= n; ++i) cin >> arr[i];     for (long long i = 1; i < n; ++i) {       long long a, b;       cin >> a >> b;       add(a, b);       add(b, a);     }     dfs1(1, 1);     dfs2(1, 1);     build(1, n, 1);     root = 1;     while (q--) {       long long t;       cin >> t;       long long v, u, x;       if (t == 1) {         cin >> v;         root = v;       } else if (t == 2) {         cin >> u >> v >> x;         long long t1 = get_lca(u, root);         long long t2 = get_lca(v, root);         long long t3 = get_lca(u, v);         long long ans = t1;         if (dep[ans] < dep[t2]) ans = t2;         if (dep[ans] < dep[t3]) ans = t3;         long long lca = get_lca(root, ans);         if (ans == root) {           update(1, x);         } else if (lca != ans) {           update(ans, x);         } else {           update(1, x);           long long s = topC(root, dep[root] - dep[ans] - 1);           update(s, -x);         }       } else {         cin >> v;         long long ans = v;         long long lca = get_lca(root, ans);         if (ans == root) {           cout << qry(1) << endl;         } else if (lca != ans) {           cout << qry(ans) << endl;         } else {           long long s = topC(root, dep[root] - dep[ans] - 1);           cout << (qry(1) - qry(s)) << endl;         }       }     }   }