#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
inline int read() {
  int x = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  return x * f;
}
struct Edge {
  int to, nex;
} e[N * 2];
int n, q, head[N], tot, rt, tid, dfn[N], pos[N], sz[N], fa[N], dep[N];
long long w[N];
inline void ade(int u, int v) {
  e[++tot].to = v;
  e[tot].nex = head[u];
  head[u] = tot;
}
void reb(int u, int pr) {
  dfn[u] = ++tid;
  pos[tid] = u;
  sz[u] = 1;
  fa[u] = pr;
  dep[u] = dep[pr] + 1;
  for (int i = head[u]; i; i = e[i].nex) {
    int v = e[i].to;
    if (v == pr) continue;
    reb(v, u);
    sz[u] += sz[v];
  }
}
int pa[N][17];
long long sum[N * 4], lazy[N * 4];
void pre_lca() {
  for (int i = 1; i <= n; i++) pa[i][0] = fa[i];
  for (int j = 1; j <= 16; j++)
    for (int i = 1; i <= n; i++) pa[i][j] = pa[pa[i][j - 1]][j - 1];
}
inline int LCA(int x, int y) {
  if (dep[x] < dep[y]) swap(x, y);
  for (int i = 16; i >= 0; i--)
    if (dep[pa[x][i]] >= dep[y]) x = pa[x][i];
  if (x == y) return x;
  for (int i = 16; i >= 0; i--)
    if (pa[x][i] != pa[y][i]) x = pa[x][i], y = pa[y][i];
  return pa[x][0];
}
inline void pushdown(int u, int l, int r) {
  if (!lazy[u]) return;
  int mid = (l + r) >> 1;
  sum[(u << 1)] += lazy[u] * (mid - l + 1);
  sum[(u << 1 | 1)] += lazy[u] * (r - mid);
  lazy[(u << 1)] += lazy[u];
  lazy[(u << 1 | 1)] += lazy[u];
  lazy[u] = 0;
}
void build(int u, int l, int r) {
  if (l == r) {
    sum[u] = w[pos[l]];
    return;
  }
  int mid = (l + r) >> 1;
  build((u << 1), l, mid);
  build((u << 1 | 1), mid + 1, r);
  sum[u] = sum[(u << 1)] + sum[(u << 1 | 1)];
}
long long query(int u, int l, int r, int be, int en) {
  if (be == l && r == en) return sum[u];
  int mid = (l + r) >> 1;
  pushdown(u, l, r);
  if (en <= mid)
    return query((u << 1), l, mid, be, en);
  else if (be > mid)
    return query((u << 1 | 1), mid + 1, r, be, en);
  else
    return query((u << 1), l, mid, be, mid) +
           query((u << 1 | 1), mid + 1, r, mid + 1, en);
}
void upd(int u, int l, int r, int be, int en, long long val) {
  if (be == l && r == en) {
    sum[u] += val * (r - l + 1);
    lazy[u] += val;
    return;
  }
  int mid = (l + r) >> 1;
  pushdown(u, l, r);
  if (en <= mid)
    upd((u << 1), l, mid, be, en, val);
  else if (be > mid)
    upd((u << 1 | 1), mid + 1, r, be, en, val);
  else
    upd((u << 1), l, mid, be, mid, val),
        upd((u << 1 | 1), mid + 1, r, mid + 1, en, val);
  sum[u] = sum[(u << 1)] + sum[(u << 1 | 1)];
}
inline int get_ch(int x) {
  int y = rt;
  for (int i = 16; i >= 0; i--)
    if (dep[pa[y][i]] > dep[x]) y = pa[y][i];
  return y;
}
inline bool in_tree(int x, int fa) {
  return dfn[x] >= dfn[fa] && dfn[x] <= dfn[fa] + sz[fa] - 1;
}
int cur_lca(int x, int y) {
  bool f1 = in_tree(x, rt), f2 = in_tree(y, rt);
  if (f1 && f2)
    return LCA(x, y);
  else if (f1 ^ f2)
    return rt;
  else {
    int l0 = LCA(x, y), l1, l2;
    if (LCA(l0, rt) != l0) return l0;
    l1 = LCA(x, rt), l2 = LCA(y, rt);
    return dep[l1] > dep[l2] ? l1 : l2;
  }
}
int main() {
  n = read();
  q = read();
  for (int i = 1; i <= n; i++) w[i] = read();
  for (int i = 1; i < n; i++) {
    int u = read(), v = read();
    ade(u, v);
    ade(v, u);
  }
  reb(1, 0);
  rt = 1;
  pre_lca();
  build(1, 1, n);
  for (int i = 1; i <= q; i++) {
    int op = read(), x = read();
    if (op == 1) {
      rt = x;
    } else if (op == 2) {
      int y = read(), z = read(), lca = cur_lca(x, y);
      if (rt == lca)
        upd(1, 1, n, 1, n, z);
      else if (!in_tree(rt, lca))
        upd(1, 1, n, dfn[lca], dfn[lca] + sz[lca] - 1, z);
      else {
        int p = lca, ch;
        ch = get_ch(p);
        upd(1, 1, n, 1, n, z);
        upd(1, 1, n, dfn[ch], dfn[ch] + sz[ch] - 1, -z);
      }
    } else {
      long long ans;
      if (x == rt)
        ans = query(1, 1, n, 1, n);
      else if (in_tree(x, rt) || LCA(rt, x) != x)
        ans = query(1, 1, n, dfn[x], dfn[x] + sz[x] - 1);
      else {
        int ch = get_ch(x);
        ans = query(1, 1, n, 1, n) -
              query(1, 1, n, dfn[ch], dfn[ch] + sz[ch] - 1);
      }
      printf("%I64d\n", ans);
    }
  }
  return 0;
}
