#include <bits/stdc++.h>
using namespace std;
const long long N = 1e5 + 10;
long long h[N], e[2 * N], ne[2 * N], idx;
void add(long long a, long long b) { e[idx] = b, ne[idx] = h[a], h[a] = idx++; }
struct node {
  long long sum, add;
};
node tr[N << 2];
long long arr[N];
long long f[N][20];
long long dep[N], fa[N], son[N], sz[N];
long long n, q;
void dfs1(long long u, long long fz) {
  fa[u] = fz;
  dep[u] = dep[fz] + 1;
  sz[u] = 1;
  f[u][0] = fz;
  for (long long i = 1; i < 20; ++i) f[u][i] = f[f[u][i - 1]][i - 1];
  for (long long i = h[u]; i != -1; i = ne[i]) {
    long long j = e[i];
    if (j == fz) continue;
    dfs1(j, u);
    sz[u] += sz[j];
    if (sz[j] > sz[son[u]]) {
      son[u] = j;
    }
  }
}
long long id[N], top[N], uid[N], tot;
void dfs2(long long u, long long topx) {
  top[u] = topx;
  id[u] = ++tot;
  uid[tot] = u;
  if (!son[u]) return;
  dfs2(son[u], topx);
  for (long long i = h[u]; i != -1; i = ne[i]) {
    long long j = e[i];
    if (j == fa[u] || j == son[u]) continue;
    dfs2(j, j);
  }
}
long long get_lca(long long a, long long b) {
  while (top[a] != top[b]) {
    if (dep[top[a]] > dep[top[b]])
      a = fa[top[a]];
    else
      b = fa[top[b]];
  }
  return dep[a] > dep[b] ? b : a;
}
long long topC(long long x, long long c) {
  for (long long i = 19; i >= 0; i--) {
    if ((1 << i) <= c) {
      x = f[x][i];
      c -= (1 << i);
    }
  }
  return x;
}
long long root;
void pushup(long long u) { tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum; }
void pushdown(long long l, long long r, long long u) {
  if (tr[u].add) {
    long long mid = l + r >> 1;
    tr[u << 1].sum += (mid - l + 1) * tr[u].add;
    tr[u << 1 | 1].sum += (r - mid) * tr[u].add;
    tr[u << 1].add += tr[u].add;
    tr[u << 1 | 1].add += tr[u].add;
    tr[u].add = 0;
  }
}
long long query(long long l, long long r, long long a, long long b,
                long long u) {
  if (l <= a && b <= r) {
    return tr[u].sum;
  }
  pushdown(a, b, u);
  long long mid = a + b >> 1;
  long long ans = 0;
  if (l <= mid) ans += query(l, r, a, mid, u << 1);
  if (r > mid) ans += query(l, r, mid + 1, b, u << 1 | 1);
  return ans;
}
void ud(long long l, long long r, long long a, long long b, long long d,
        long long u) {
  if (l <= a && b <= r) {
    tr[u].add += d;
    tr[u].sum += (b - a + 1) * d;
    return;
  }
  pushdown(a, b, u);
  long long mid = a + b >> 1;
  if (l <= mid) ud(l, r, a, mid, d, u << 1);
  if (r > mid) ud(l, r, mid + 1, b, d, u << 1 | 1);
  pushup(u);
}
void update(long long u, long long x) {
  ud(id[u], id[u] + sz[u] - 1, 1, n, x, 1);
}
long long qry(long long u) { return query(id[u], id[u] + sz[u] - 1, 1, n, 1); }
void build(long long l, long long r, long long u) {
  tr[u].add = 0;
  if (l == r) {
    tr[u].sum = arr[uid[l]];
    return;
  }
  long long mid = l + r >> 1;
  build(l, mid, u << 1);
  build(mid + 1, r, u << 1 | 1);
  pushup(u);
}
int main() {
  ios::sync_with_stdio(false);
  std::cin.tie(0);
  memset(h, -1, sizeof h);
  cin >> n >> q;
  for (long long i = 1; i <= n; ++i) cin >> arr[i];
  for (long long i = 1; i < n; ++i) {
    long long a, b;
    cin >> a >> b;
    add(a, b);
    add(b, a);
  }
  dfs1(1, 1);
  dfs2(1, 1);
  build(1, n, 1);
  root = 1;
  while (q--) {
    long long t;
    cin >> t;
    long long v, u, x;
    if (t == 1) {
      cin >> v;
      root = v;
    } else if (t == 2) {
      cin >> u >> v >> x;
      long long t1 = get_lca(u, root);
      long long t2 = get_lca(v, root);
      long long t3 = get_lca(u, v);
      long long ans = t1;
      if (dep[ans] < dep[t2]) ans = t2;
      if (dep[ans] < dep[t3]) ans = t3;
      long long lca = get_lca(root, ans);
      if (ans == root) {
        update(1, x);
      } else if (lca != ans) {
        update(ans, x);
      } else {
        update(1, x);
        long long s = topC(root, dep[root] - dep[ans] - 1);
        update(s, -x);
      }
    } else {
      cin >> v;
      long long ans = v;
      long long lca = get_lca(root, ans);
      if (ans == root) {
        cout << qry(1) << endl;
      } else if (lca != ans) {
        cout << qry(ans) << endl;
      } else {
        long long s = topC(root, dep[root] - dep[ans] - 1);
        cout << (qry(1) - qry(s)) << endl;
      }
    }
  }
}
