#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int n, q, opt, x, y, z, rt, val[maxn];
int cnt, head[maxn];
struct Edge {
  int to, next;
} e[maxn << 1];
void add(int u, int v) {
  e[++cnt].to = v;
  e[cnt].next = head[u];
  head[u] = cnt;
}
int siz[maxn], fa[maxn][18], dep[maxn], son[maxn], top[maxn], pos[maxn], tot,
    rk[maxn];
void dfs1(int u) {
  siz[u] = 1;
  for (int i = head[u]; i; i = e[i].next) {
    int v = e[i].to;
    if (v == fa[u][0]) continue;
    fa[v][0] = u;
    dep[v] = dep[u] + 1;
    dfs1(v);
    siz[u] += siz[v];
    if (!son[u] || siz[v] > siz[son[u]]) son[u] = v;
  }
}
void dfs2(int u, int tp) {
  top[u] = tp, pos[u] = ++tot, rk[tot] = u;
  if (son[u]) dfs2(son[u], tp);
  for (int i = head[u]; i; i = e[i].next) {
    int v = e[i].to;
    if (v != son[u] && v != fa[u][0]) dfs2(v, v);
  }
}
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]][0];
  }
  return dep[x] < dep[y] ? x : y;
}
void Init() {
  for (int j = 1; j <= 17; ++j) {
    for (int i = 1; i <= n; ++i) fa[i][j] = fa[fa[i][j - 1]][j - 1];
  }
}
int find(int x, int k) {
  for (int i = 0; i <= 17; ++i)
    if (k & (1 << i)) x = fa[x][i];
  return x;
}
struct Node {
  long long sum, lazy;
} tree[maxn << 2];
void pushup(int rt) {
  tree[rt].sum = tree[rt << 1].sum + tree[rt << 1 | 1].sum;
}
void build(int rt, int l, int r) {
  if (l == r) {
    tree[rt].sum = val[rk[l]];
    return;
  }
  int mid = l + r >> 1;
  build(rt << 1, l, mid);
  build(rt << 1 | 1, mid + 1, r);
  pushup(rt);
}
void pushdown(int rt, int l, int r) {
  if (tree[rt].lazy) {
    int mid = l + r >> 1;
    long long x = tree[rt].lazy;
    tree[rt << 1].lazy += x, tree[rt << 1 | 1].lazy += x;
    tree[rt << 1].sum += x * (mid - l + 1),
        tree[rt << 1 | 1].sum += x * (r - mid);
    tree[rt].lazy = 0;
  }
}
void update(int rt, int l, int r, int L, int R, int k) {
  if (L > R) return;
  if (L <= l && R >= r) {
    tree[rt].sum += (long long)(r - l + 1) * k;
    tree[rt].lazy += k;
    return;
  }
  pushdown(rt, l, r);
  int mid = l + r >> 1;
  if (L <= mid) update(rt << 1, l, mid, L, R, k);
  if (R > mid) update(rt << 1 | 1, mid + 1, r, L, R, k);
  pushup(rt);
}
long long query(int rt, int l, int r, int L, int R) {
  if (L > R) return 0;
  if (L <= l && R >= r) return tree[rt].sum;
  pushdown(rt, l, r);
  int mid = l + r >> 1;
  long long res = 0;
  if (L <= mid) res += query(rt << 1, l, mid, L, R);
  if (R > mid) res += query(rt << 1 | 1, mid + 1, r, L, R);
  pushup(rt);
  return res;
}
int main() {
  scanf("%d%d", &n, &q);
  for (int i = 1; i <= n; ++i) scanf("%d", &val[i]);
  for (int i = 1; i < n; ++i) scanf("%d%d", &x, &y), add(x, y), add(y, x);
  dfs1(1), dfs2(1, 1), build(1, 1, n), rt = 1, Init();
  for (int i = 1; i <= q; ++i) {
    scanf("%d", &opt);
    if (opt == 1)
      scanf("%d", &rt);
    else if (opt == 2) {
      scanf("%d%d%d", &x, &y, &z);
      if (x == rt || y == rt)
        tree[1].lazy += z, tree[1].sum += (long long)n * z;
      else {
        int flag1 = pos[x] >= pos[rt] && pos[x] <= pos[rt] + siz[rt] - 1,
            flag2 = pos[y] >= pos[rt] && pos[y] <= pos[rt] + siz[rt] - 1;
        int LCA = lca(x, y);
        if (flag1 && flag2) {
          if (LCA == rt)
            tree[1].lazy += z, tree[1].sum += (long long)n * z;
          else
            update(1, 1, n, pos[LCA], pos[LCA] + siz[LCA] - 1, z);
        } else if (flag1 || flag2)
          tree[1].lazy += z, tree[1].sum += (long long)n * z;
        else {
          if (find(rt, dep[rt] - dep[LCA]) != LCA)
            update(1, 1, n, pos[LCA], pos[LCA] + siz[LCA] - 1, z);
          else {
            if (dep[x] < dep[y]) swap(x, y);
            int p;
            int op1 = lca(x, rt), op2 = lca(y, rt);
            if (dep[op1] > dep[op2])
              p = find(rt, dep[rt] - dep[op1] - 1);
            else
              p = find(rt, dep[rt] - dep[op2] - 1);
            update(1, 1, n, 1, pos[p] - 1, z),
                update(1, 1, n, pos[p] + siz[p], n, z);
          }
        }
      }
    } else {
      scanf("%d", &x);
      int LCA = lca(x, rt);
      if (x == rt)
        printf("%lld\n", tree[1].sum);
      else if (x == LCA) {
        int y = find(rt, dep[rt] - dep[x] - 1);
        printf("%lld\n", query(1, 1, n, 1, pos[y] - 1) +
                             query(1, 1, n, pos[y] + siz[y], n));
      } else
        printf("%lld\n", query(1, 1, n, pos[x], pos[x] + siz[x] - 1));
    }
  }
  return 0;
}
