#include <bits/stdc++.h>
using namespace std;
vector<int> g[110000];
int n, x, y, z, q, opt, root, a[110000], b[110000], l[110000], r[110000],
    f[110000][20], deep[110000];
struct segment_tree {
  struct node {
    int l, r;
    long long add, sum;
  } t[4 * 110000];
  void update(int x) { t[x].sum = t[x * 2].sum + t[x * 2 + 1].sum; }
  void push(int x) {
    if (t[x].l == t[x].r) return;
    if (t[x].add) {
      int ls = x * 2, rs = x * 2 + 1;
      t[ls].sum += 1ll * (t[ls].r - t[ls].l + 1) * t[x].add;
      t[rs].sum += 1ll * (t[rs].r - t[rs].l + 1) * t[x].add;
      t[ls].add += t[x].add;
      t[rs].add += t[x].add;
      t[x].add = 0;
    }
  }
  void build(int x, int l, int r) {
    t[x].l = l;
    t[x].r = r;
    if (l == r) {
      t[x].sum = a[b[l]];
      return;
    }
    int mid = (l + r) / 2;
    build(x * 2, l, mid);
    build(x * 2 + 1, mid + 1, r);
    update(x);
  }
  void add(int x, int l, int r, int k) {
    if (t[x].l > r || t[x].r < l) return;
    push(x);
    if (l <= t[x].l && t[x].r <= r) {
      t[x].add += k;
      t[x].sum += 1ll * (t[x].r - t[x].l + 1) * k;
      return;
    }
    add(x * 2, l, r, k);
    add(x * 2 + 1, l, r, k);
    update(x);
  }
  long long ask(int x, int l, int r) {
    if (t[x].r < l || t[x].l > r) return 0;
    push(x);
    if (l <= t[x].l && t[x].r <= r) return t[x].sum;
    return ask(x * 2, l, r) + ask(x * 2 + 1, l, r);
  }
} T;
void dfs(int x, int fa) {
  b[++b[0]] = x;
  l[x] = r[x] = b[0];
  f[x][0] = fa;
  for (int i = 1; f[x][i - 1]; i++) f[x][i] = f[f[x][i - 1]][i - 1];
  deep[x] = deep[fa] + 1;
  for (auto t : g[x])
    if (t != fa) {
      dfs(t, x);
      r[x] = r[t];
    }
}
int lca(int x, int y) {
  if (deep[x] < deep[y]) swap(x, y);
  int k = deep[x] - deep[y];
  for (int i = 0; (1 << i) <= k; i++)
    if ((1 << i) & k) x = f[x][i];
  if (x == y) return x;
  for (int i = 19; i >= 0; i--)
    if (f[x][i] != f[y][i]) {
      x = f[x][i];
      y = f[y][i];
    }
  return f[x][0];
}
int jump(int x, int k) {
  for (int i = 0; i < 20; i++)
    if ((1 << i) & k) x = f[x][i];
  return x;
}
void add(int x, int k) {
  if (x == root) {
    T.add(1, 1, n, k);
    return;
  }
  if (deep[root] > deep[x]) {
    int t = jump(root, deep[root] - deep[x] - 1);
    if (f[t][0] == x) {
      T.add(1, 1, n, k);
      T.add(1, l[t], r[t], -k);
      return;
    }
  }
  T.add(1, l[x], r[x], k);
}
long long calc(int x) {
  if (x == root) return T.ask(1, 1, n);
  if (deep[root] > deep[x]) {
    int t = jump(root, deep[root] - deep[x] - 1);
    if (f[t][0] == x) return T.ask(1, 1, n) - T.ask(1, l[t], r[t]);
  }
  return T.ask(1, l[x], r[x]);
}
int main() {
  scanf("%d%d", &n, &q);
  for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
  for (int i = 1; i < n; i++) {
    scanf("%d%d", &x, &y);
    g[x].push_back(y);
    g[y].push_back(x);
  }
  dfs(1, 0);
  T.build(1, 1, n);
  root = 1;
  for (int i = 1; i <= q; i++) {
    scanf("%d", &opt);
    if (opt == 1) scanf("%d", &root);
    if (opt == 2) {
      scanf("%d%d%d", &x, &y, &z);
      int u = lca(x, y), v = lca(x, root), w = lca(y, root);
      int t = u;
      if (deep[v] > deep[t]) t = v;
      if (deep[w] > deep[t]) t = w;
      add(t, z);
    }
    if (opt == 3) {
      scanf("%d", &x);
      printf("%lld\n", calc(x));
    }
  }
  return 0;
}
