#include <bits/stdc++.h>
using namespace std;
long long n, m, a[100005];
long long dfn[100005], head[100005], idx, rev[100005], cnt, size[100005],
    top[100005], dep[100005], fa[100005], son[100005];
long long sum[100005 << 2], tag[100005 << 2];
void push_tag(long long p, long long l, long long r, long long v) {
  tag[p] += v;
  sum[p] += (r - l + 1) * v;
}
void push_down(long long p, long long l, long long r) {
  long long mid = (l + r) >> 1;
  if (tag[p] != 0) {
    push_tag(p << 1, l, mid, tag[p]);
    push_tag(p << 1 | 1, mid + 1, r, tag[p]);
    tag[p] = 0;
  }
}
void push_up(long long p) { sum[p] = sum[p << 1] + sum[p << 1 | 1]; }
void build(long long p, long long l, long long r) {
  if (l == r) {
    sum[p] = a[rev[l]];
    return;
  }
  long long mid = (l + r) >> 1;
  build(p << 1, l, mid);
  build(p << 1 | 1, mid + 1, r);
  push_up(p);
}
void modify(long long p, long long l, long long r, long long ql, long long qr,
            long long v) {
  if (ql > qr) return;
  if (ql <= l && qr >= r) {
    push_tag(p, l, r, v);
    return;
  }
  long long mid = (l + r) >> 1;
  push_down(p, l, r);
  if (ql <= mid) modify(p << 1, l, mid, ql, qr, v);
  if (qr > mid) modify(p << 1 | 1, mid + 1, r, ql, qr, v);
  push_up(p);
}
long long query(long long p, long long l, long long r, long long ql,
                long long qr) {
  if (ql > qr) return 0;
  if (ql <= l && qr >= r) return sum[p];
  push_down(p, l, r);
  long long mid = (l + r) >> 1;
  long long res = 0;
  if (ql <= mid) res += query(p << 1, l, mid, ql, qr);
  if (qr > mid) res += query(p << 1 | 1, mid + 1, r, ql, qr);
  return res;
}
struct edge {
  long long v, next;
} e[100005 << 1];
void add(long long u, long long v) {
  e[++idx].v = v;
  e[idx].next = head[u];
  head[u] = idx;
}
void dfs1(long long x, long long f) {
  fa[x] = f;
  dep[x] = dep[f] + 1;
  size[x] = 1;
  for (long long i = head[x]; i; i = e[i].next) {
    long long y = e[i].v;
    if (y == f) continue;
    dfs1(y, x);
    size[x] += size[y];
    if (size[y] > size[son[x]]) son[x] = y;
  }
}
void dfs2(long long x) {
  if (x == son[fa[x]])
    top[x] = top[fa[x]];
  else
    top[x] = x;
  dfn[x] = ++cnt;
  rev[cnt] = x;
  if (son[x]) dfs2(son[x]);
  for (long long i = head[x]; i; i = e[i].next) {
    long long y = e[i].v;
    if (y == fa[x] || y == son[x]) continue;
    dfs2(y);
  }
}
pair<long long, long long> LCA(long long x, long long y) {
  long long Son = 0;
  while (top[x] != top[y]) {
    if (dep[top[x]] < dep[top[y]]) swap(x, y);
    if (fa[top[x]] == y) Son = top[x];
    x = fa[top[x]];
  }
  if (dep[x] > dep[y]) swap(x, y);
  if (!Son) Son = son[x];
  return make_pair(x, Son);
}
long long root;
long long nowlca(long long x, long long y) {
  long long z = LCA(x, y).first;
  if (x == y) return x;
  if (z == root) return root;
  if (dep[x] > dep[y]) swap(x, y);
  if (z == x) {
    if (dfn[y] <= dfn[root] && dfn[y] + size[y] - 1 >= dfn[root]) return y;
    if (dfn[x] <= dfn[root] && dfn[x] + size[x] - 1 >= dfn[root])
      return LCA(y, root).first;
    return x;
  }
  if (dfn[y] <= dfn[root] && dfn[y] + size[y] - 1 >= dfn[root]) return y;
  if (dfn[x] <= dfn[root] && dfn[x] + size[x] - 1 >= dfn[root]) return x;
  if (dfn[z] <= dfn[root] && dfn[z] + size[z] - 1 >= dfn[root]) {
    long long lca1 = LCA(x, root).first, lca2 = LCA(y, root).first;
    if (dep[lca1] < dep[lca2]) swap(lca1, lca2);
    return lca1;
  }
  return z;
}
void add(long long x, long long y, long long v) {
  long long z = nowlca(x, y);
  if (root == z) {
    modify(1, 1, n, 1, n, v);
    return;
  }
  pair<long long, long long> lca = LCA(root, z);
  if (lca.first != z) {
    modify(1, 1, n, dfn[z], dfn[z] + size[z] - 1, v);
    return;
  } else {
    modify(1, 1, n, 1, dfn[lca.second] - 1, v);
    modify(1, 1, n, dfn[lca.second] + size[lca.second], n, v);
    return;
  }
}
long long ask(long long x) {
  if (root == x) return query(1, 1, n, 1, n);
  pair<long long, long long> lca = LCA(x, root);
  if (lca.first != x) return query(1, 1, n, dfn[x], dfn[x] + size[x] - 1);
  return query(1, 1, n, 1, dfn[lca.second] - 1) +
         query(1, 1, n, dfn[lca.second] + size[lca.second], n);
}
signed main() {
  scanf("%lld%lld", &n, &m);
  root = 1;
  for (long long i = 1; i <= n; i++) scanf("%lld", &a[i]);
  for (long long i = 1; i < n; i++) {
    long long u, v;
    scanf("%lld%lld", &u, &v);
    add(u, v);
    add(v, u);
  }
  dfs1(1, 0);
  dfs2(1);
  build(1, 1, n);
  while (m--) {
    long long op, x, y, z;
    scanf("%lld%lld", &op, &x);
    if (op == 1) root = x;
    if (op == 2) {
      scanf("%lld%lld", &y, &z);
      add(x, y, z);
    }
    if (op == 3) printf("%lld\n", ask(x));
  }
}
