#include <bits/stdc++.h>
using namespace std;
int n, q, to[100005 << 1], nxt[100005 << 1], head[100005], cnt;
int fir[100005], sec[100005], tot, fa[100005][31], lg[100005], dep[100005],
    root = 1;
long long vl[100005 << 2], w[100005], f[100005], col[100005 << 2];
void add(int x, int y) { to[++cnt] = y, nxt[cnt] = head[x], head[x] = cnt; }
void dfs(int now) {
  fir[now] = ++tot, dep[now] = dep[fa[now][0]] + 1, f[fir[now]] = w[now];
  for (int i = head[now]; i; i = nxt[i]) {
    int y = to[i];
    if (y != fa[now][0]) {
      fa[y][0] = now;
      dfs(y);
    }
  }
  sec[now] = tot;
}
void dp() {
  for (int j = 1; j <= lg[n]; j++) {
    for (int i = 1; i <= n; i++) {
      fa[i][j] = fa[fa[i][j - 1]][j - 1];
    }
  }
}
int lca(int x, int y) {
  if (dep[x] < dep[y]) {
    swap(x, y);
  }
  for (int i = lg[n]; i >= 0; i--) {
    if (dep[fa[x][i]] >= dep[y]) {
      x = fa[x][i];
    }
  }
  if (x == y) {
    return x;
  }
  int ret = 0;
  for (int i = lg[n]; i >= 0; i--) {
    if (fa[x][i] == fa[y][i]) {
      ret = fa[x][i];
    } else {
      x = fa[x][i];
      y = fa[y][i];
    }
  }
  return ret;
}
void build(int lx, int rx, int nx) {
  if (lx == rx) {
    vl[nx] = f[lx], col[nx] = 0;
    return;
  }
  int mid = (lx + rx) >> 1;
  build(lx, mid, nx << 1);
  build(mid + 1, rx, (nx << 1) | 1);
  vl[nx] = vl[nx << 1] + vl[(nx << 1) | 1];
}
void pushdown(int nx, int len) {
  if (col[nx]) {
    col[nx << 1] += col[nx];
    col[(nx << 1) | 1] += col[nx];
    vl[nx << 1] += col[nx] * (len - (len >> 1));
    vl[(nx << 1) | 1] += col[nx] * (len >> 1);
    col[nx] = 0;
  }
}
void update(int lm, int rm, long long aim, int lx, int rx, int nx) {
  if (lm <= lx && rm >= rx) {
    col[nx] += aim;
    vl[nx] += aim * (rx - lx + 1);
    return;
  }
  pushdown(nx, rx - lx + 1);
  int mid = (lx + rx) >> 1;
  if (lm <= mid) {
    update(lm, rm, aim, lx, mid, nx << 1);
  }
  if (rm > mid) {
    update(lm, rm, aim, mid + 1, rx, (nx << 1) | 1);
  }
  vl[nx] = vl[nx << 1] + vl[(nx << 1) | 1];
}
long long query(int lm, int rm, int lx, int rx, int nx) {
  if (lm <= lx && rm >= rx) {
    return vl[nx];
  }
  pushdown(nx, rx - lx + 1);
  int mid = (lx + rx) >> 1;
  long long ret = 0;
  if (lm <= mid) {
    ret += query(lm, rm, lx, mid, nx << 1);
  }
  if (rm > mid) {
    ret += query(lm, rm, mid + 1, rx, (nx << 1) | 1);
  }
  return ret;
}
int find(int x) {
  int tmp = root;
  for (int i = lg[n]; i >= 0; i--) {
    if (dep[fa[tmp][i]] > dep[x]) {
      tmp = fa[tmp][i];
    }
  }
  return tmp;
}
int main() {
  scanf("%d%d", &n, &q);
  for (int i = 2; i <= n; i++) {
    lg[i] = lg[i >> 1] + 1;
  }
  for (int i = 1; i <= n; i++) {
    scanf("%I64d", &w[i]);
  }
  for (int i = 1, ui, vi; i < n; i++) {
    scanf("%d%d", &ui, &vi);
    add(ui, vi);
    add(vi, ui);
  }
  dfs(1);
  dp();
  build(1, n, 1);
  for (int i = 1; i <= q; i++) {
    int opt;
    scanf("%d", &opt);
    if (opt == 1) {
      int tmp;
      scanf("%d", &tmp);
      root = tmp;
    } else if (opt == 2) {
      int ui, vi;
      long long xi;
      scanf("%d%d%I64d", &ui, &vi, &xi);
      int now = lca(ui, vi);
      int tmp;
      tmp = lca(ui, root);
      if (dep[tmp] > dep[now]) {
        now = tmp;
      }
      tmp = lca(vi, root);
      if (dep[tmp] > dep[now]) {
        now = tmp;
      }
      if (now == root) {
        update(1, n, xi, 1, n, 1);
      } else if (fir[now] < fir[root] && sec[now] >= sec[root]) {
        update(1, n, xi, 1, n, 1);
        int rt = find(now);
        update(fir[rt], sec[rt], -xi, 1, n, 1);
      } else {
        update(fir[now], sec[now], xi, 1, n, 1);
      }
    } else {
      int now;
      scanf("%d", &now);
      long long ret = 0;
      if (now == root) {
        ret += vl[1];
      } else if (fir[now] < fir[root] && sec[now] >= sec[root]) {
        ret += vl[1];
        int rt = find(now);
        ret -= query(fir[rt], sec[rt], 1, n, 1);
      } else {
        ret += query(fir[now], sec[now], 1, n, 1);
      }
      printf("%I64d\n", ret);
    }
  }
  return 0;
}
