#include <bits/stdc++.h>   using namespace std;   long long n, m, a[100005];   long long dfn[100005], head[100005], idx, rev[100005], cnt, size[100005],       top[100005], dep[100005], fa[100005], son[100005];   long long sum[100005 << 2], tag[100005 << 2];   void push_tag(long long p, long long l, long long r, long long v) {     tag[p] += v;     sum[p] += (r - l + 1) * v;   }   void push_down(long long p, long long l, long long r) {     long long mid = (l + r) >> 1;     if (tag[p] != 0) {       push_tag(p << 1, l, mid, tag[p]);       push_tag(p << 1 | 1, mid + 1, r, tag[p]);       tag[p] = 0;     }   }   void push_up(long long p) { sum[p] = sum[p << 1] + sum[p << 1 | 1]; }   void build(long long p, long long l, long long r) {     if (l == r) {       sum[p] = a[rev[l]];       return;     }     long long mid = (l + r) >> 1;     build(p << 1, l, mid);     build(p << 1 | 1, mid + 1, r);     push_up(p);   }   void modify(long long p, long long l, long long r, long long ql, long long qr,               long long v) {     if (ql > qr) return;     if (ql <= l && qr >= r) {       push_tag(p, l, r, v);       return;     }     long long mid = (l + r) >> 1;     push_down(p, l, r);     if (ql <= mid) modify(p << 1, l, mid, ql, qr, v);     if (qr > mid) modify(p << 1 | 1, mid + 1, r, ql, qr, v);     push_up(p);   }   long long query(long long p, long long l, long long r, long long ql,                   long long qr) {     if (ql > qr) return 0;     if (ql <= l && qr >= r) return sum[p];     push_down(p, l, r);     long long mid = (l + r) >> 1;     long long res = 0;     if (ql <= mid) res += query(p << 1, l, mid, ql, qr);     if (qr > mid) res += query(p << 1 | 1, mid + 1, r, ql, qr);     return res;   }   struct edge {     long long v, next;   } e[100005 << 1];   void add(long long u, long long v) {     e[++idx].v = v;     e[idx].next = head[u];     head[u] = idx;   }   void dfs1(long long x, long long f) {     fa[x] = f;     dep[x] = dep[f] + 1;     size[x] = 1;     for (long long i = head[x]; i; i = e[i].next) {       long long y = e[i].v;       if (y == f) continue;       dfs1(y, x);       size[x] += size[y];       if (size[y] > size[son[x]]) son[x] = y;     }   }   void dfs2(long long x) {     if (x == son[fa[x]])       top[x] = top[fa[x]];     else       top[x] = x;     dfn[x] = ++cnt;     rev[cnt] = x;     if (son[x]) dfs2(son[x]);     for (long long i = head[x]; i; i = e[i].next) {       long long y = e[i].v;       if (y == fa[x] || y == son[x]) continue;       dfs2(y);     }   }   pair<long long, long long> LCA(long long x, long long y) {     long long Son = 0;     while (top[x] != top[y]) {       if (dep[top[x]] < dep[top[y]]) swap(x, y);       if (fa[top[x]] == y) Son = top[x];       x = fa[top[x]];     }     if (dep[x] > dep[y]) swap(x, y);     if (!Son) Son = son[x];     return make_pair(x, Son);   }   long long root;   long long nowlca(long long x, long long y) {     long long z = LCA(x, y).first;     if (x == y) return x;     if (z == root) return root;     if (dep[x] > dep[y]) swap(x, y);     if (z == x) {       if (dfn[y] <= dfn[root] && dfn[y] + size[y] - 1 >= dfn[root]) return y;       if (dfn[x] <= dfn[root] && dfn[x] + size[x] - 1 >= dfn[root])         return LCA(y, root).first;       return x;     }     if (dfn[y] <= dfn[root] && dfn[y] + size[y] - 1 >= dfn[root]) return y;     if (dfn[x] <= dfn[root] && dfn[x] + size[x] - 1 >= dfn[root]) return x;     if (dfn[z] <= dfn[root] && dfn[z] + size[z] - 1 >= dfn[root]) {       long long lca1 = LCA(x, root).first, lca2 = LCA(y, root).first;       if (dep[lca1] < dep[lca2]) swap(lca1, lca2);       return lca1;     }     return z;   }   void add(long long x, long long y, long long v) {     long long z = nowlca(x, y);     if (root == z) {       modify(1, 1, n, 1, n, v);       return;     }     pair<long long, long long> lca = LCA(root, z);     if (lca.first != z) {       modify(1, 1, n, dfn[z], dfn[z] + size[z] - 1, v);       return;     } else {       modify(1, 1, n, 1, dfn[lca.second] - 1, v);       modify(1, 1, n, dfn[lca.second] + size[lca.second], n, v);       return;     }   }   long long ask(long long x) {     if (root == x) return query(1, 1, n, 1, n);     pair<long long, long long> lca = LCA(x, root);     if (lca.first != x) return query(1, 1, n, dfn[x], dfn[x] + size[x] - 1);     return query(1, 1, n, 1, dfn[lca.second] - 1) +            query(1, 1, n, dfn[lca.second] + size[lca.second], n);   }   signed main() {     scanf( %lld%lld , &n, &m);     root = 1;     for (long long i = 1; i <= n; i++) scanf( %lld , &a[i]);     for (long long i = 1; i < n; i++) {       long long u, v;       scanf( %lld%lld , &u, &v);       add(u, v);       add(v, u);     }     dfs1(1, 0);     dfs2(1);     build(1, 1, n);     while (m--) {       long long op, x, y, z;       scanf( %lld%lld , &op, &x);       if (op == 1) root = x;       if (op == 2) {         scanf( %lld%lld , &y, &z);         add(x, y, z);       }       if (op == 3) printf( %lld n , ask(x));     }   }