#include <bits/stdc++.h>
#pragma GCC optimize(3)
using namespace std;
int n, q, opt, x, y, z, aa, bb, cc,
    cap = 1, cnt, tot, out, fh, a[100010], at[100010], h[100010], dep[100010],
    size[100010], dad[100010], son[100010], id[100010], top[100010],
    fa[100010][18];
char c;
struct Edge {
  int next, to;
} e[200010];
struct SegT {
  long long s, l;
} t[400010];
int read() {
  out = 0, fh = 1, c = getchar();
  while (c < 48 || c > 57) {
    if (c == 45) {
      fh = -1;
    }
    c = getchar();
  }
  while (c >= 48 && c <= 57) {
    out = (out << 3) + (out << 1) + (c & 15), c = getchar();
  }
  return out * fh;
}
void Add(int x, int y) { e[++cnt].next = h[x], e[cnt].to = y, h[x] = cnt; }
void DFS1(int x) {
  dep[x] = dep[dad[x]] + 1, size[x] = 1;
  for (int i = h[x]; i; i = e[i].next) {
    int y = e[i].to;
    if (y ^ dad[x]) {
      dad[y] = x, fa[y][0] = x;
      DFS1(y);
      size[x] += size[y];
      if (size[son[x]] < size[y]) {
        son[x] = y;
      }
    }
  }
}
void DFS2(int x) {
  id[x] = ++tot, at[tot] = a[x], top[x] = x == son[dad[x]] ? top[dad[x]] : x;
  for (int i = 1; i <= 17; ++i) {
    fa[x][i] = fa[fa[x][i - 1]][i - 1];
  }
  if (!son[x]) {
    return;
  }
  DFS2(son[x]);
  for (int i = h[x]; i; i = e[i].next) {
    int y = e[i].to;
    if (y ^ dad[x] && y ^ son[x]) {
      DFS2(y);
    }
  }
}
void DFS(int x) {
  DFS1(x);
  DFS2(x);
}
void Pushdown(int k, int l, int r) {
  if (!t[k].l) {
    return;
  }
  int mid = l + r >> 1;
  t[k << 1].l += t[k].l, t[k << 1 | 1].l += t[k].l,
      t[k << 1].s += t[k].l * (mid - l + 1),
      t[k << 1 | 1].s += t[k].l * (r - mid), t[k].l = 0;
}
void Build(int k, int l, int r) {
  if (l == r) {
    t[k].s = at[l];
    return;
  }
  int mid = l + r >> 1;
  Build(k << 1, l, mid);
  Build(k << 1 | 1, mid + 1, r);
  t[k].s = t[k << 1].s + t[k << 1 | 1].s;
}
void Change(int k, int l, int r, int ll, int rr, long long x) {
  if (r < ll || rr < l) {
    return;
  }
  if (ll <= l && r <= rr) {
    t[k].s += x * (r - l + 1), t[k].l += x;
    return;
  }
  Pushdown(k, l, r);
  int mid = l + r >> 1;
  Change(k << 1, l, mid, ll, rr, x);
  Change(k << 1 | 1, mid + 1, r, ll, rr, x);
  t[k].s = t[k << 1].s + t[k << 1 | 1].s;
}
long long Query(int k, int l, int r, int ll, int rr) {
  if (r < ll || rr < l) {
    return 0;
  }
  if (ll <= l && r <= rr) {
    return t[k].s;
  }
  Pushdown(k, l, r);
  int mid = l + r >> 1;
  return Query(k << 1, l, mid, ll, rr) + Query(k << 1 | 1, mid + 1, r, ll, rr);
}
int LCA(int x, int y) {
  while (top[x] ^ top[y]) {
    if (dep[top[x]] < dep[top[y]]) {
      x ^= y ^= x ^= y;
    }
    x = dad[top[x]];
  }
  return dep[x] > dep[y] ? y : x;
}
int Son(int x, int p) {
  for (int i = 0; i <= 17; ++i) {
    if (p & 1) {
      x = fa[x][i];
    }
    p >>= 1;
  }
  return x;
}
int main() {
  n = read(), q = read();
  for (int i = 1; i <= n; ++i) {
    a[i] = read();
  }
  for (int i = 1; i < n; ++i) {
    x = read(), y = read();
    Add(x, y);
    Add(y, x);
  }
  DFS(1);
  Build(1, 1, n);
  while (q--) {
    opt = read();
    if (opt == 1) {
      cap = read();
    }
    if (opt == 2) {
      x = read(), y = read(), z = read(), aa = LCA(x, y), bb = LCA(x, cap),
      cc = LCA(y, cap),
      x = dep[aa] > dep[bb]   ? dep[aa] > dep[cc] ? aa : cc
          : dep[bb] > dep[cc] ? bb
                              : cc;
      if (x == cap) {
        Change(1, 1, n, 1, n, z);
      } else {
        if (id[x] < id[cap] && id[x] + size[x] > id[cap]) {
          x = Son(cap, dep[cap] - dep[x] - 1);
          Change(1, 1, n, 1, id[x] - 1, z);
          Change(1, 1, n, id[x] + size[x], n, z);
        } else {
          Change(1, 1, n, id[x], id[x] + size[x] - 1, z);
        }
      }
    }
    if (opt == 3) {
      x = read();
      if (x == cap) {
        printf("%lld\n", t[1].s);
      } else {
        if (id[x] < id[cap] && id[x] + size[x] > id[cap]) {
          x = Son(cap, dep[cap] - dep[x] - 1);
          printf("%lld\n", t[1].s - Query(1, 1, n, id[x], id[x] + size[x] - 1));
        } else {
          printf("%lld\n", Query(1, 1, n, id[x], id[x] + size[x] - 1));
        }
      }
    }
  }
  return 0;
}
