#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
const int N = 1e5 + 7;
const int st = 22;
int n, c[N], tin[N], tout[N], up[N][30], d[N], timer, v, u, q, tn = 1, x, f,
                                                               root;
long long t[N * 4], lazy[N * 4];
vector<int> g[N];
vector<long long> a;
void dfs(int v, int p) {
  tin[v] = ++timer;
  d[v] = d[p] + 1;
  a.push_back(c[v]);
  up[v][0] = p;
  for (int i = 1; i <= st; i++) up[v][i] = up[up[v][i - 1]][i - 1];
  for (auto to : g[v])
    if (to != p) dfs(to, v);
  tout[v] = timer;
  return;
}
bool upper(int v, int u) { return (tin[v] <= tin[u] && tout[u] <= tout[v]); }
int lca(int v, int u) {
  if (upper(v, u)) return v;
  if (upper(u, v)) return u;
  for (int i = st; i >= 0; i--)
    if (!upper(up[v][i], u)) v = up[v][i];
  return up[v][0];
}
void push(int v, int len) {
  t[v << 1] += lazy[v] * len;
  t[(v << 1) + 1] += lazy[v] * len;
  lazy[v << 1] += lazy[v];
  lazy[(v << 1) + 1] += lazy[v];
  lazy[v] = 0;
  return;
}
void update(int v, int tl, int tr, int l, int r, long long x) {
  if (r <= tl || tr <= l) return;
  if (l <= tl && tr <= r) {
    lazy[v] += x;
    t[v] += (tr - tl) * x;
    return;
  }
  push(v, (tr - tl) / 2);
  int mid = (tl + tr) / 2;
  update(v << 1, tl, mid, l, r, x);
  update((v << 1) + 1, mid, tr, l, r, x);
  t[v] = t[v << 1] + t[(v << 1) + 1];
  return;
}
long long query(int v, int tl, int tr, int l, int r) {
  if (r <= tl || tr <= l) return 0;
  if (l <= tl && tr <= r) return t[v];
  push(v, (tr - tl) / 2);
  int mid = (tl + tr) / 2;
  return query(v << 1, tl, mid, l, r) + query((v << 1) + 1, mid, tr, l, r);
}
long long query(int v) { return query(1, 0, tn, tin[v] - 1, tout[v]); }
void update(int v, long long x) {
  update(1, 0, tn, tin[v] - 1, tout[v], x);
  return;
}
int upp(int v, int u) {
  for (int i = st; i >= 0; i--)
    if (u & (1 << i)) v = up[v][i];
  return v;
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> q;
  while (tn < n) tn <<= 1;
  for (int i = 0; i < n; i++) cin >> c[i];
  for (int i = 0; i < n - 1; i++) {
    cin >> v >> u;
    v--;
    u--;
    g[v].push_back(u);
    g[u].push_back(v);
  }
  dfs(0, 0);
  for (int i = 0; i < n; i++) t[i + tn] = a[i];
  for (int i = tn - 1; i >= 1; i--) t[i] = t[i << 1] + t[(i << 1) + 1];
  while (q--) {
    cin >> f;
    if (f == 1) {
      cin >> v;
      root = --v;
    }
    if (f == 2) {
      cin >> v >> u >> x;
      v--;
      u--;
      int l = lca(v, u);
      if (l == root || (upper(l, root) && (upper(root, v) || upper(root, u)))) {
        update(0, x);
        continue;
      }
      if (upper(l, root)) {
        update(0, x);
        int lv = lca(root, v);
        int lu = lca(root, u);
        if (d[lv] < d[lu]) swap(lv, lu);
        update(upp(root, d[root] - d[lv] - 1), -x);
        continue;
      }
      update(l, x);
    }
    if (f == 3) {
      cin >> u;
      u--;
      if (root == u)
        cout << query(0) << '\n';
      else if (upper(u, root))
        cout << query(0) - query(upp(root, d[root] - d[u] - 1)) << '\n';
      else
        cout << query(u) << '\n';
    }
  }
  return 0;
}
