#include <bits/stdc++.h>
using namespace std;
long long int a[4 * int(1e5 + 100)], lazy[4 * int(1e5 + 100)],
    b[int(1e5 + 100)], c[int(1e5 + 100)], at[int(1e5 + 100)],
    ft[int(1e5 + 100)], m = 0, par[int(1e5 + 100)], l[int(1e5 + 100)],
                        sp[int(1e5 + 100)][20], u, v, n, q, x, lc, root = 0;
vector<long long int> g[int(1e5 + 100)];
void dfs(long long int s = 0, long long int p = -1) {
  par[s] = p;
  c[m] = b[s];
  at[s] = ft[s] = m++;
  if (p != -1)
    l[s] = l[p] + 1;
  else
    l[s] = 1;
  for (long long int i = 0; i < g[s].size(); i++)
    if (g[s][i] != p) dfs(g[s][i], s);
  ft[s] = m;
}
void pre() {
  for (long long int i = 0; i < n; i++)
    for (long long int j = 0; (1 << j) < n; j++) sp[i][j] = -1;
  for (long long int i = 0; i < n; i++) sp[i][0] = par[i];
  for (long long int j = 1; (1 << j) < n; j++)
    for (long long int i = 0; i < n; i++)
      if (sp[i][j - 1] != -1) sp[i][j] = sp[sp[i][j - 1]][j - 1];
}
long long int lca(long long int u, long long int v) {
  long long int i, j;
  if (l[u] < l[v]) swap(u, v);
  for (j = 0; (1 << j) < l[u]; j++)
    ;
  j--;
  for (i = j; i >= 0; i--)
    if (l[u] - (1 << i) >= l[v]) u = sp[u][i];
  if (u == v) return u;
  for (i = j; i >= 0; i--)
    if (sp[u][i] != -1 && sp[u][i] != sp[v][i]) {
      u = sp[u][i];
      v = sp[v][i];
    }
  return par[u];
}
long long int getkth(long long int u, long long int d) {
  for (long long int i = 20 - 1; i >= 0; i--)
    if (d & (1 << i)) u = sp[u][i];
  return u;
}
void build(long long int l, long long int h, long long int pos) {
  if (l == h)
    a[pos - 1] = c[l - 1];
  else {
    build(l, (l + h) / 2, 2 * pos);
    build((l + h) / 2 + 1, h, 2 * pos + 1);
    a[pos - 1] = a[2 * pos - 1] + a[2 * pos];
  }
}
long long int query(long long int l, long long int h, long long int le,
                    long long int ri, long long int pos) {
  if (lazy[pos - 1]) {
    a[pos - 1] += (h - l + 1) * lazy[pos - 1];
    if (l != h) {
      lazy[2 * pos - 1] += lazy[pos - 1];
      lazy[2 * pos] += lazy[pos - 1];
    }
    lazy[pos - 1] = 0;
  }
  if (l >= le && h <= ri)
    return a[pos - 1];
  else if (ri < l || le > h)
    return 0;
  else {
    long long int x = query(l, (l + h) / 2, le, ri, 2 * pos);
    long long int y = query((l + h) / 2 + 1, h, le, ri, 2 * pos + 1);
    return x + y;
  }
}
void updateutil(long long int l, long long int h, long long int le,
                long long int ri, long long int pos, long long int item) {
  if (lazy[pos - 1]) {
    a[pos - 1] += (h - l + 1) * lazy[pos - 1];
    if (l != h) {
      lazy[2 * pos - 1] += lazy[pos - 1];
      lazy[2 * pos] += lazy[pos - 1];
    }
    lazy[pos - 1] = 0;
  }
  if (ri < l || le > h)
    return;
  else if (l >= le && h <= ri) {
    a[pos - 1] += item * (h - l + 1);
    if (l != h) {
      lazy[2 * pos - 1] += item;
      lazy[2 * pos] += item;
    }
  } else {
    updateutil(l, (l + h) / 2, le, ri, 2 * pos, item);
    updateutil((l + h) / 2 + 1, h, le, ri, 2 * pos + 1, item);
    a[pos - 1] = a[2 * pos - 1] + a[2 * pos];
  }
}
void update(long long int n, long long int l, long long int r,
            long long int item) {
  updateutil(1, n, l, r, 1, item);
}
long long int find(long long int u, long long int v) {
  long long int lca1 = lca(u, v), lca2 = lca(u, root), lca3 = lca(v, root);
  if (l[lca1] >= l[lca2] && l[lca1] >= l[lca3]) return lca1;
  if (l[lca2] >= l[lca1] && l[lca2] >= l[lca3]) return lca2;
  return lca3;
}
long long int find1(long long int v) {
  if (v == root) return query(1, n, 1, n, 1);
  if (at[v] > at[root] || ft[v] < ft[root])
    return query(1, n, 1 + at[v], ft[v], 1);
  u = getkth(root, l[root] - l[v] - 1);
  return (query(1, n, 1, n, 1) - query(1, n, 1 + at[u], ft[u], 1));
}
void find3(long long int u, long long int v, long long int x) {
  long long int lc = find(u, v);
  if (lc == root)
    update(n, 1, n, x);
  else if (at[lc] > at[root] || ft[lc] < ft[root])
    update(n, 1 + at[lc], ft[lc], x);
  else {
    u = getkth(root, l[root] - l[lc] - 1);
    update(n, 1, n, x);
    update(n, 1 + at[u], ft[u], -x);
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  cin >> n >> q;
  for (long long int i = 0; i < n; i++) cin >> b[i];
  for (long long int i = 1; i < n; i++) {
    cin >> u >> v;
    u--;
    v--;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  dfs();
  pre();
  build(1, n, 1);
  long long int s;
  while (q--) {
    cin >> s;
    if (s == 1) {
      cin >> root;
      root--;
    }
    if (s == 2) {
      cin >> u >> v >> x;
      u--;
      v--;
      find3(u, v, x);
    }
    if (s == 3) {
      cin >> v;
      v--;
      cout << find1(v) << endl;
    }
  }
}
