#include <bits/stdc++.h>
using namespace std;
const int maxn = 100000 + 10;
int d[maxn], reald[maxn], n;
vector<int> G[maxn];
int in[maxn], out[maxn], pa[maxn][21], time_stamp;
int root;
struct Seg {
  long long T[maxn * 4], lazy[maxn * 4];
  void build(int l, int r, int id) {
    if (l == r)
      T[id] = reald[l];
    else {
      int mid = (l + r) >> 1;
      build(l, mid, id << 1);
      build(mid + 1, r, id << 1 | 1);
      T[id] = T[id << 1] + T[id << 1 | 1];
    }
    lazy[id] = 0;
  }
  void pushdown(int l, int r, int id) {
    int mid = (l + r) >> 1;
    if (lazy[id]) {
      T[id << 1] += lazy[id] * (mid + 1 - l);
      T[id << 1 | 1] += lazy[id] * (r - mid);
      lazy[id << 1] += lazy[id];
      lazy[id << 1 | 1] += lazy[id];
      lazy[id] = 0;
    }
  }
  void add(int l, int r, int id, int a, int b, long long v) {
    if (a <= l && r <= b)
      T[id] += (r - l + 1) * v, lazy[id] += v;
    else {
      pushdown(l, r, id);
      int mid = (l + r) >> 1;
      if (b <= mid)
        add(l, mid, id << 1, a, b, v);
      else if (a > mid)
        add(mid + 1, r, id << 1 | 1, a, b, v);
      else {
        add(l, mid, id << 1, a, mid, v);
        add(mid + 1, r, id << 1 | 1, mid + 1, b, v);
      }
      T[id] = T[id << 1] + T[id << 1 | 1];
    }
  }
  long long query(int l, int r, int id, int a, int b) {
    if (a <= l && r <= b)
      return T[id];
    else {
      pushdown(l, r, id);
      int mid = (l + r) >> 1;
      long long ans = 0;
      if (b <= mid)
        ans = query(l, mid, id << 1, a, b);
      else if (a > mid)
        ans = query(mid + 1, r, id << 1 | 1, a, b);
      else {
        ans = query(l, mid, id << 1, a, mid) +
              query(mid + 1, r, id << 1 | 1, mid + 1, b);
      }
      T[id] = T[id << 1] + T[id << 1 | 1];
      return ans;
    }
  }
} T;
void dfs(int x, int p);
bool is_anc(int x, int y) { return (in[x] <= in[y] && out[y] <= out[x]); }
bool is_on_path(int u, int v, int x) { return is_anc(x, u) && is_anc(v, x); }
int lca(int x, int y) {
  if (is_anc(x, y)) return x;
  if (is_anc(y, x)) return y;
  int gap = 20;
  while (!is_anc(pa[x][0], y)) {
    if (!is_anc(pa[x][gap], y)) x = pa[x][gap];
    gap--;
  }
  return pa[x][0];
}
void add(int u, int v, int x) {
  int lc = lca(u, v);
  if (!is_anc(lc, root)) {
    assert(lc != root);
    T.add(1, n, 1, in[lc], out[lc], x);
  } else if (is_on_path(u, lc, root) || is_on_path(v, lc, root)) {
    T.add(1, n, 1, 1, n, x);
  } else {
    assert(lc != root);
    int r = root;
    int gap = 20;
    while (!is_on_path(u, lc, pa[r][0]) && !is_on_path(v, lc, pa[r][0])) {
      while (
          (!is_on_path(u, lc, pa[r][gap]) && !is_on_path(v, lc, pa[r][gap])) &&
          (!is_anc(pa[r][gap], u) && !is_anc(pa[r][gap], v)))
        r = pa[r][gap];
      gap -= 1;
    }
    T.add(1, n, 1, 1, n, x);
    T.add(1, n, 1, in[r], out[r], -x);
  }
}
long long query(int u) {
  if (u == root) return T.query(1, n, 1, 1, n);
  if (!is_anc(u, root)) {
    return T.query(1, n, 1, in[u], out[u]);
  } else {
    int r = root;
    int gap = 20;
    while (pa[r][0] != u) {
      while (pa[r][gap] != u && is_anc(u, pa[r][gap])) r = pa[r][gap];
      gap--;
    }
    return T.query(1, n, 1, 1, n) - T.query(1, n, 1, in[r], out[r]);
  }
}
int main() {
  int q;
  while (scanf("%d%d", &n, &q) == 2) {
    for (int i = 0; i <= n; i++) G[i].clear();
    for (int i = 1; i <= n; i++) scanf("%d", &d[i]);
    for (int i = 1, a, b; i < n; i++) {
      scanf("%d%d", &a, &b);
      G[a].push_back(b);
      G[b].push_back(a);
    }
    time_stamp = 0;
    root = 1;
    dfs(root, root);
    for (int i = 1; i <= 20; i++) {
      for (int j = 1; j <= n; j++) {
        pa[j][i] = pa[pa[j][i - 1]][i - 1];
      }
    }
    T.build(1, out[root], 1);
    int op, u, v, x;
    while (q--) {
      scanf("%d", &op);
      if (op == 1) {
        scanf("%d", &root);
      } else if (op == 2) {
        scanf("%d%d%d", &u, &v, &x);
        add(u, v, x);
      } else {
        scanf("%d", &u);
        printf("%lld\n", query(u));
      }
    }
  }
  return 0;
}
void dfs(int x, int p) {
  in[x] = ++time_stamp;
  pa[x][0] = p;
  reald[in[x]] = d[x];
  for (auto y : G[x])
    if (y != p) dfs(y, x);
  out[x] = time_stamp;
}
