#include <bits/stdc++.h>
using namespace std;
inline long long read() {
  long long x = 0, f = 1;
  char ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (isdigit(ch)) {
    x = x * 10 + ch - 48;
    ch = getchar();
  }
  return x * f;
}
long long n, k;
long long st[200001];
struct aa {
  long long u, v;
  long long next;
} edge[200001 * 4];
long long head[200001];
long long cnt = 0;
void add_edge(long long u, long long v) {
  cnt++;
  edge[cnt].u = u;
  edge[cnt].v = v;
  edge[cnt].next = head[u];
  head[u] = cnt;
}
long long root = 0;
long long f[200001][29];
long long son[200001];
long long size[200001];
long long depth[200001];
long long ed[200001];
long long tot = 0;
long long id[200001];
long long top[200001];
void dfs1(long long u, long long fa) {
  f[u][0] = fa;
  for (long long i = 1; i <= 21; i++) {
    f[u][i] = f[f[u][i - 1]][i - 1];
  }
  depth[u] = depth[fa] + 1;
  size[u] = 1;
  for (long long i = head[u]; i; i = edge[i].next) {
    long long v = edge[i].v;
    if (v != fa) {
      dfs1(v, u);
      if (size[son[u]] < size[v]) {
        son[u] = v;
      }
      size[u] += size[v];
    }
  }
}
void dfs2(long long u, long long tp) {
  tot++;
  id[u] = tot;
  ed[tot] = st[u];
  top[u] = tp;
  if (son[u]) {
    dfs2(son[u], tp);
    for (long long i = head[u]; i; i = edge[i].next) {
      long long v = edge[i].v;
      if (v != son[u] && v != f[u][0]) {
        dfs2(v, v);
      }
    }
  }
}
struct qw {
  long long l, r, val;
  long long add;
} a[1600001];
void up(long long i) { a[i].val = a[i * 2].val + a[i * 2 + 1].val; }
void down(long long i) {
  long long x = a[i].add;
  a[i * 2].add += x;
  a[i * 2 + 1].add += x;
  a[i * 2].val += (a[i * 2].r - a[i * 2].l + 1) * x;
  a[i * 2 + 1].val += (a[i * 2 + 1].r - a[i * 2 + 1].l + 1) * x;
  a[i].add = 0;
}
void build(long long i, long long l, long long r) {
  a[i].l = l;
  a[i].r = r;
  if (l == r) {
    a[i].val = ed[a[i].l];
    return;
  }
  long long mid = (l + r) / 2;
  build(i * 2, l, mid);
  build(i * 2 + 1, mid + 1, r);
  up(i);
}
void update(long long i, long long l, long long r, long long k) {
  if (a[i].l == l && a[i].r == r) {
    a[i].add += k;
    a[i].val += (a[i].r - a[i].l + 1) * k;
    return;
  }
  down(i);
  long long mid = (a[i].l + a[i].r) / 2;
  if (mid >= r) {
    update(i * 2, l, r, k);
  } else {
    if (mid < l) {
      update(i * 2 + 1, l, r, k);
    } else {
      update(i * 2, l, mid, k);
      update(i * 2 + 1, mid + 1, r, k);
    }
  }
  up(i);
}
long long query(long long i, long long l, long long r) {
  if (a[i].l == l && a[i].r == r) {
    return a[i].val;
  }
  down(i);
  long long mid = (a[i].l + a[i].r) / 2;
  if (mid >= r) {
    return query(i * 2, l, r);
  } else {
    if (mid < l) {
      return query(i * 2 + 1, l, r);
    } else {
      return (query(i * 2, l, mid) + query(i * 2 + 1, mid + 1, r));
    }
  }
}
long long find(long long u, long long to) {
  for (long long i = 21; i >= 0; i--) {
    if (depth[f[u][i]] > depth[to]) {
      u = f[u][i];
    }
  }
  return u;
}
long long lca(long long x, long long y) {
  if (depth[x] < depth[y]) {
    swap(x, y);
  }
  while (depth[x] > depth[y]) {
    x = f[x][(long long)log2(depth[x] - depth[y])];
  }
  if (x == y) {
    return x;
  }
  for (long long i = 21; i >= 0; i--) {
    if (f[x][i] != f[y][i]) {
      x = f[x][i];
      y = f[y][i];
    }
  }
  return f[x][0];
}
long long lcaq(long long x, long long y) {
  long long v1 = lca(x, y);
  long long v2 = lca(x, root);
  long long v3 = lca(y, root);
  if (depth[v1] < depth[v2]) {
    v1 = v2;
  }
  if (depth[v1] < depth[v3]) {
    v1 = v3;
  }
  return v1;
}
signed main() {
  cin >> n >> k;
  for (long long i = 1; i <= n; i++) {
    cin >> st[i];
  }
  for (long long i = 1; i <= n - 1; i++) {
    long long u, v;
    cin >> u >> v;
    add_edge(u, v);
    add_edge(v, u);
  }
  root = 1;
  dfs1(1, 0);
  dfs2(1, 1);
  build(1, 1, n);
  for (long long i = 1; i <= k; i++) {
    long long opt;
    opt = read();
    if (opt == 1) {
      long long v;
      cin >> v;
      root = v;
    }
    if (opt == 2) {
      long long a, b, k;
      cin >> a >> b >> k;
      long long x = lcaq(a, b);
      if (x == root) {
        update(1, 1, n, k);
      } else {
        if (id[root] >= id[x] && id[root] <= id[x] + size[x] - 1) {
          long long at = find(root, x);
          update(1, 1, n, k);
          update(1, id[at], id[at] + size[at] - 1, -k);
        } else {
          update(1, id[x], id[x] + size[x] - 1, k);
        }
      }
    }
    if (opt == 3) {
      long long x;
      cin >> x;
      if (x == root) {
        cout << query(1, 1, n) << endl;
        ;
      } else {
        if (id[root] >= id[x] && id[root] <= id[x] + size[x] - 1) {
          long long at = find(root, x);
          long long val =
              query(1, 1, n) - query(1, id[at], id[at] + size[at] - 1);
          cout << val << endl;
        } else {
          cout << query(1, id[x], id[x] + size[x] - 1) << endl;
          ;
        }
      }
    }
  }
  return 0;
}
