#include <bits/stdc++.h>
#pragma GCC optimize(3)
using namespace std;
const long long N = 200010;
inline long long read() {
  long long s = 0, w = 1;
  register char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') w = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9')
    s = (s << 3) + (s << 1) + (ch ^ 48), ch = getchar();
  return s * w;
}
long long n, Q, a[N], root;
long long f[N], d[N], siz[N], son[N], top[N], st[N], ed[N], nowid, s[N];
long long head[N], maxE;
struct Edge {
  long long nxt, to;
} e[N << 1];
inline void Add(long long u, long long v) {
  e[++maxE].nxt = head[u];
  head[u] = maxE;
  e[maxE].to = v;
}
void DFS1(long long x, long long fa) {
  f[x] = fa, d[x] = d[fa] + 1, siz[x] = 1;
  for (register long long i = head[x]; i; i = e[i].nxt) {
    long long v = e[i].to;
    if (v == fa) continue;
    DFS1(v, x);
    siz[x] += siz[v];
    if (siz[v] > siz[son[x]]) son[x] = v;
  }
}
void DFS2(long long x, long long topf) {
  top[x] = topf, st[x] = ++nowid, s[nowid] = x;
  if (!son[x]) {
    ed[x] = nowid;
    return;
  }
  DFS2(son[x], topf);
  for (register long long i = head[x]; i; i = e[i].nxt) {
    long long v = e[i].to;
    if (v == f[x] || v == son[x]) continue;
    DFS2(v, v);
  }
  ed[x] = nowid;
}
inline long long LCA(long long x, long long y) {
  while (top[x] ^ top[y]) {
    if (d[top[x]] < d[top[y]]) swap(x, y);
    x = f[top[x]];
  }
  if (d[x] > d[y]) swap(x, y);
  return x;
}
inline long long Func(long long x, long long y) {
  while (top[x] ^ top[y]) {
    if (f[top[x]] == y) return top[x];
    x = f[top[x]];
  }
  return son[y];
}
long long sum[N << 2], tag[N << 2];
inline void Push_Up(long long x) { sum[x] = sum[(x << 1)] + sum[(x << 1 | 1)]; }
inline void Push_Down(long long x, long long l, long long r) {
  tag[(x << 1)] += tag[x], tag[(x << 1 | 1)] += tag[x];
  long long mid = (l + r) / 2;
  sum[(x << 1)] += tag[x] * (mid - l + 1),
      sum[(x << 1 | 1)] += tag[x] * (r - mid);
  tag[x] = 0;
}
void Build(long long x, long long l, long long r) {
  if (l == r) {
    sum[x] = a[s[l]];
    return;
  }
  long long mid = (l + r) / 2;
  Build((x << 1), l, mid);
  Build((x << 1 | 1), mid + 1, r);
  Push_Up(x);
}
void UpDate(long long u, long long v, long long l, long long r, long long x,
            long long k) {
  if (l >= u && r <= v) {
    tag[x] += k;
    sum[x] += k * (r - l + 1);
    return;
  }
  if (tag[x]) Push_Down(x, l, r);
  long long mid = (l + r) / 2;
  if (u <= mid) UpDate(u, v, l, mid, (x << 1), k);
  if (v > mid) UpDate(u, v, mid + 1, r, (x << 1 | 1), k);
  Push_Up(x);
}
long long Ask(long long u, long long v, long long l, long long r, long long x) {
  if (l >= u && r <= v) return sum[x];
  if (tag[x]) Push_Down(x, l, r);
  long long mid = (l + r) / 2, tt = 0;
  if (u <= mid) tt += Ask(u, v, l, mid, (x << 1));
  if (v > mid) tt += Ask(u, v, mid + 1, r, (x << 1 | 1));
  return tt;
}
inline long long GetLCA(long long x, long long y) {
  if (d[x] > d[y]) swap(x, y);
  long long g1 = LCA(x, y);
  long long g2 = LCA(x, root);
  long long g3 = LCA(y, root);
  if (g2 == g3) return g1;
  if (g1 == x || g1 == g2) return g3;
  return g2;
}
inline void Modify(long long x, long long k) {
  if (x == root)
    sum[1] += k * n, tag[1] += k;
  else if (st[root] >= st[x] && ed[root] <= ed[x]) {
    long long z = Func(root, x);
    if (st[z] > 1) UpDate(1, st[z] - 1, 1, n, 1, k);
    if (ed[z] < n) UpDate(ed[z] + 1, n, 1, n, 1, k);
  } else
    UpDate(st[x], ed[x], 1, n, 1, k);
}
inline long long Query(long long x) {
  if (x == root) return sum[1];
  if (st[root] >= st[x] && ed[root] <= ed[x]) {
    long long z = Func(root, x);
    long long tt = 0;
    if (st[z] > 1) tt += Ask(1, st[z] - 1, 1, n, 1);
    if (ed[z] < n) tt += Ask(ed[z] + 1, n, 1, n, 1);
    return tt;
  }
  return Ask(st[x], ed[x], 1, n, 1);
}
signed main() {
  n = read(), Q = read();
  for (register long long i = 1; i <= n; i++) a[i] = read();
  for (register long long i = 1; i < n; i++) {
    long long u, v;
    u = read(), v = read();
    Add(u, v), Add(v, u);
  }
  DFS1(1, 0), DFS2(1, 1);
  Build(1, 1, n);
  root = 1;
  for (register long long i = 1; i <= Q; i++) {
    long long opt = read();
    if (opt == 1) root = read();
    if (opt == 2) {
      long long u, v, k;
      u = read(), v = read(), k = read();
      long long tt = GetLCA(u, v);
      Modify(tt, k);
    }
    if (opt == 3) {
      long long x = read();
      printf("%lld\n", Query(x));
    }
  }
  return 0;
}
