#include <bits/stdc++.h>
using namespace std;
vector<int> G[100005];
int timer, Q[100005], pre[100005], sz[100005], dep[100005], anc[100005][20];
void dfs(int u, int f, int d) {
  pre[u] = ++timer;
  Q[timer] = u;
  sz[u] = 1;
  dep[u] = d;
  anc[u][0] = f;
  for (int i = 1; (1 << i) <= d; i++) anc[u][i] = anc[anc[u][i - 1]][i - 1];
  for (int v : G[u])
    if (!pre[v]) {
      dfs(v, u, d + 1);
      sz[u] += sz[v];
    }
}
bool isanc(int u, int v) {
  if (pre[u] <= pre[v] && pre[v] < pre[u] + sz[u]) return 1;
  return 0;
}
int getanc(int u, int d) {
  for (int i = 0; (1 << i) <= d; i++)
    if (d & (1 << i)) u = anc[u][i];
  return u;
}
int lca(int u, int v) {
  if (dep[u] < dep[v]) swap(u, v);
  u = getanc(u, dep[u] - dep[v]);
  if (u == v) return u;
  int d = 20;
  while (d--) {
    if ((1 << d) > dep[u]) continue;
    if (anc[u][d] == anc[v][d]) continue;
    u = anc[u][d];
    v = anc[v][d];
  }
  return anc[u][0];
}
int a[100005];
long long seg[262144], tag[262144];
void build(int o, int l, int r) {
  if (l == r)
    seg[o] = a[Q[l]];
  else {
    int m = (l + r) / 2;
    build(o * 2, l, m);
    build(o * 2 + 1, m + 1, r);
    seg[o] = seg[o * 2] + seg[o * 2 + 1];
  }
}
void modify(int o, int l, int r, int ml, int mr, long long mv) {
  if (ml <= l && r <= mr)
    seg[o] += mv * (r - l + 1), tag[o] += mv;
  else {
    int m = (l + r) / 2;
    if (ml <= m) modify(o * 2, l, m, ml, mr, mv);
    if (mr > m) modify(o * 2 + 1, m + 1, r, ml, mr, mv);
    seg[o] = seg[o * 2] + seg[o * 2 + 1] + tag[o] * (r - l + 1);
  }
}
long long query(int o, int l, int r, int ql, int qr, long long now) {
  if (ql <= l && r <= qr) return seg[o] + now * (r - l + 1);
  int m = (l + r) / 2;
  now += tag[o];
  long long ret = 0;
  if (ql <= m) ret += query(o * 2, l, m, ql, qr, now);
  if (qr > m) ret += query(o * 2 + 1, m + 1, r, ql, qr, now);
  return ret;
}
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
  for (int i = 1; i < n; i++) {
    int x, y;
    scanf("%d%d", &x, &y);
    G[x].push_back(y);
    G[y].push_back(x);
  }
  dfs(1, 0, 0);
  build(1, 1, n);
  int root = 1;
  while (m--) {
    int op;
    scanf("%d", &op);
    if (op == 1) {
      int x;
      scanf("%d", &x);
      root = x;
    } else if (op == 2) {
      int x, y, v;
      scanf("%d%d%d", &x, &y, &v);
      int z1 = lca(x, root), z2 = lca(y, root), z3 = lca(x, y),
          z = z1 ^ z2 ^ z3;
      if (z == root)
        modify(1, 1, n, 1, n, v);
      else if (isanc(z, root)) {
        modify(1, 1, n, 1, n, v);
        z = getanc(root, dep[root] - dep[z] - 1);
        modify(1, 1, n, pre[z], pre[z] + sz[z] - 1, -v);
      } else
        modify(1, 1, n, pre[z], pre[z] + sz[z] - 1, v);
    } else {
      int x;
      scanf("%d", &x);
      if (x == root)
        printf("%lld\n", seg[1]);
      else if (isanc(x, root)) {
        x = getanc(root, dep[root] - dep[x] - 1);
        printf("%lld\n",
               seg[1] - query(1, 1, n, pre[x], pre[x] + sz[x] - 1, 0));
      } else
        printf("%lld\n", query(1, 1, n, pre[x], pre[x] + sz[x] - 1, 0));
    }
  }
  return 0;
}
