#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10;
int p[N][23], head[N], cnt, id, rt, n;
int ps[N], dfn[N], dep[N], sz[N], fa[N], top[N], son[N];
long long sum[N << 2], tag[N << 2], val[N];
struct ed {
  int to, next;
} e[N * 2];
void ad(int x, int y) {
  e[++cnt] = (ed){y, head[x]};
  head[x] = cnt;
  e[++cnt] = (ed){x, head[y]};
  head[y] = cnt;
}
void dfs1(int u, int last) {
  p[u][0] = last;
  for (int j = 1; j <= 22; j++) p[u][j] = p[p[u][j - 1]][j - 1];
  sz[u] = 1, dep[u] = dep[last] + 1, fa[u] = last;
  for (int k = head[u]; k; k = e[k].next) {
    int v = e[k].to;
    if (v == last) continue;
    dfs1(v, u);
    sz[u] += sz[v];
    if (sz[v] > sz[son[u]]) son[u] = v;
  }
}
void dfs2(int u, int tp) {
  dfn[u] = ++id, ps[id] = u, top[u] = tp;
  if (son[u]) dfs2(son[u], tp);
  for (int k = head[u]; k; k = e[k].next) {
    int v = e[k].to;
    if (v != fa[u] && v != son[u]) dfs2(v, v);
  }
}
void push_up(int c) { sum[c] = sum[c << 1] + sum[c << 1 | 1]; }
void push_down(int c, int l, int r) {
  if (!tag[c]) return;
  int mid = l + r >> 1;
  tag[c << 1] += tag[c], sum[c << 1] += tag[c] * (mid - l + 1);
  tag[c << 1 | 1] += tag[c], sum[c << 1 | 1] += tag[c] * (r - mid);
  tag[c] = 0;
}
void build(int l, int r, int c) {
  if (l == r) {
    sum[c] = val[ps[l]];
    return;
  }
  int mid = l + r >> 1;
  build(l, mid, c << 1);
  build(mid + 1, r, c << 1 | 1);
  push_up(c);
}
int L, R;
long long t;
void add(int l, int r, int c) {
  if (L <= l && R >= r) {
    sum[c] += (r - l + 1) * t;
    tag[c] += t;
    return;
  }
  push_down(c, l, r);
  int mid = l + r >> 1;
  if (L <= mid) add(l, mid, c << 1);
  if (R > mid) add(mid + 1, r, c << 1 | 1);
  push_up(c);
}
void query(int l, int r, int c) {
  if (L <= l && R >= r) {
    t += sum[c];
    return;
  }
  push_down(c, l, r);
  int mid = l + r >> 1;
  if (L <= mid) query(l, mid, c << 1);
  if (R > mid) query(mid + 1, r, c << 1 | 1);
  push_up(c);
}
int Up(int x, int d) {
  for (int j = 22; j >= 0; j--)
    if (d & (1 << j)) x = p[x][j];
  return x;
}
int get_lca(int x, int y) {
  if (dep[x] < dep[y]) swap(x, y);
  for (int j = 22; j >= 0; j--)
    if (dep[x] - (1 << j) >= dep[y]) x = p[x][j];
  if (x == y) return x;
  for (int j = 22; j >= 0; j--)
    if (p[x][j] != p[y][j]) x = p[x][j], y = p[y][j];
  return p[x][0];
}
int anc(int x, int y, int z) {
  int l1 = get_lca(x, y), l2 = get_lca(y, z);
  if (dep[l1] < dep[l2]) l1 = l2;
  int l3 = get_lca(x, z);
  if (dep[l1] < dep[l3]) l1 = l3;
  return l1;
}
int main() {
  int q, x, y;
  scanf("%d%d", &n, &q);
  long long al = 0, tot = 0, d;
  for (int i = 1; i <= n; i++) scanf("%lld", &val[i]), al += val[i];
  for (int i = 1; i < n; i++) scanf("%d%d", &x, &y), ad(x, y);
  dfs1(1, 0);
  dfs2(1, 1);
  build(1, n, 1);
  while (q--) {
    int op;
    scanf("%d", &op);
    switch (op) {
      case 1: {
        scanf("%d", &rt);
        break;
      }
      case 2: {
        scanf("%d%d%lld", &x, &y, &d);
        int a = anc(rt, x, y);
        if (a == rt)
          tot += d, al += d * n;
        else if (dfn[a] <= dfn[rt] && dfn[a] + sz[a] - 1 >= dfn[rt]) {
          int tmp = Up(rt, dep[rt] - dep[a] - 1);
          tot += d, al += d * (n - sz[tmp]);
          L = dfn[tmp], R = dfn[tmp] + sz[tmp] - 1, t = -d;
          add(1, n, 1);
        } else
          al += d * sz[a], L = dfn[a], R = dfn[a] + sz[a] - 1, t = d,
                           add(1, n, 1);
        break;
      }
      default: {
        scanf("%d", &x);
        if (x == rt)
          printf("%lld\n", al);
        else if (dfn[x] <= dfn[rt] && dfn[x] + sz[x] - 1 >= dfn[rt]) {
          int tmp = Up(rt, dep[rt] - dep[x] - 1);
          L = dfn[tmp], R = dfn[tmp] + sz[tmp] - 1, t = 0;
          query(1, n, 1);
          printf("%lld\n", al - (t + tot * sz[tmp]));
        } else {
          L = dfn[x], R = dfn[x] + sz[x] - 1, t = 0;
          query(1, n, 1);
          printf("%lld\n", t + tot * sz[x]);
        }
      }
    }
  }
  return 0;
}
