#include <bits/stdc++.h>
using namespace std;
const long long N = 1e5 + 10;
const long long oo = 1e9;
long long n, cnt, root = 1, q;
long long val[N], la[4 * N], st[N], en[N], pr[N][30], ver[N], node[4 * N],
    hi[N];
vector<long long> vi[N];
void dfs(long long pre, long long u, long long h) {
  pr[u][0] = pre;
  hi[u] = h;
  st[u] = ++cnt;
  ver[cnt] = u;
  for (long long i = 0; i < vi[u].size(); ++i) {
    long long v = vi[u][i];
    if (v != pre) dfs(u, v, h + 1);
  }
  en[u] = cnt;
}
void true_val(long long i, long long l, long long r) {
  if (l > r || !la[i]) return;
  node[i] += (r - l + 1) * la[i];
  if (l != r) {
    la[(i << 1)] += la[i];
    la[(i << 1) + 1] += la[i];
  }
  la[i] = 0;
}
void build(long long i, long long l, long long r) {
  if (l > r) return;
  if (l == r) {
    node[i] = val[ver[l]];
    return;
  }
  long long mid = (l + r) / 2;
  build((i << 1), l, mid);
  build((i << 1) + 1, mid + 1, r);
  node[i] = node[(i << 1)] + node[(i << 1) + 1];
}
void upd(long long i, long long l, long long r, long long a, long long b,
         long long value) {
  true_val(i, l, r);
  if (a > r || b < l || l > r) return;
  if (a <= l && r <= b) {
    node[i] += (r - l + 1) * value;
    if (l != r) {
      la[(i << 1)] += value;
      la[(i << 1) + 1] += value;
    }
    return;
  }
  long long mid = (l + r) / 2;
  upd((i << 1), l, mid, a, b, value);
  upd((i << 1) + 1, mid + 1, r, a, b, value);
  node[i] = node[(i << 1)] + node[(i << 1) + 1];
}
long long getm(long long i, long long l, long long r, long long a,
               long long b) {
  true_val(i, l, r);
  if (l > r || a > r || b < l) return 0;
  if (a <= l && r <= b) return node[i];
  long long mid = (l + r) / 2;
  return getm((i << 1), l, mid, a, b) + getm((i << 1) + 1, mid + 1, r, a, b);
}
long long LCA(long long u, long long v) {
  if (hi[u] < hi[v]) swap(u, v);
  for (long long i = 20; i >= 0; --i)
    if (pr[u][i] != -1 && hi[pr[u][i]] >= hi[v]) u = pr[u][i];
  for (long long i = 20; i >= 0; --i)
    if (pr[u][i] != -1 && pr[v][i] != -1 && pr[u][i] != pr[v][i])
      u = pr[u][i], v = pr[v][i];
  if (u != v) return pr[u][0];
  return u;
}
signed main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> q;
  for (long long i = 0; i <= n; ++i)
    for (long long j = 0; j <= 20; ++j) pr[i][j] = -1;
  for (long long i = 1; i <= n; ++i) cin >> val[i];
  for (long long i = 1; i <= n - 1; ++i) {
    long long x, y;
    cin >> x >> y;
    vi[x].push_back(y);
    vi[y].push_back(x);
  }
  dfs(1, 1, 1);
  build(1, 1, n);
  for (long long i = 1; i <= 20; ++i)
    for (long long j = 1; j <= n; ++j)
      if (pr[j][i - 1] != -1) pr[j][i] = pr[pr[j][i - 1]][i - 1];
  while (q--) {
    long long t;
    cin >> t;
    if (t == 1) {
      long long x;
      cin >> x;
      root = x;
    } else if (t == 2) {
      long long u, v, value;
      cin >> u >> v >> value;
      long long pr1 = LCA(u, v);
      long long pr2 = LCA(u, root);
      if (hi[pr2] > hi[pr1]) swap(pr1, pr2);
      pr2 = LCA(v, root);
      if (hi[pr2] > hi[pr1]) swap(pr1, pr2);
      if (st[pr1] > st[root] || en[pr1] < st[root])
        upd(1, 1, n, st[pr1], en[pr1], value);
      else {
        upd(1, 1, n, 1, n, value);
        if (pr1 == root) continue;
        long long tmp = root;
        for (long long i = 20; i >= 0; --i)
          if (pr[tmp][i] != -1 && hi[pr[tmp][i]] > hi[pr1]) tmp = pr[tmp][i];
        upd(1, 1, n, st[tmp], en[tmp], -value);
      }
    } else {
      long long x;
      cin >> x;
      long long res = 0ll;
      if (st[x] > st[root] || en[x] < st[root])
        res = getm(1, 1, n, st[x], en[x]);
      else if (x != root) {
        res = getm(1, 1, n, 1, n);
        long long tmp = root;
        for (long long i = 20; i >= 0; --i)
          if (pr[tmp][i] != -1 && hi[pr[tmp][i]] > hi[x]) tmp = pr[tmp][i];
        res -= getm(1, 1, n, st[tmp], en[tmp]);
      } else
        res = getm(1, 1, n, 1, n);
      cout << res << '\n';
    }
  }
}
