#include <bits/stdc++.h>
using namespace std;
const int LOG = 22;
const int N = 300000 + 5;
char chr;
int OP;
inline void Read(int &x) {
  OP = 0;
  chr = getchar();
  while (chr < '0' || chr > '9') {
    if (chr == '-') OP = 1;
    chr = getchar();
  }
  x = 0;
  while (chr >= '0' && chr <= '9') {
    x = (x << 1) + (x << 3) + (chr ^ '0');
    chr = getchar();
  }
  if (OP) x = -x;
}
int n, Q, rt, clk, Log[N], line[N], rw[N], dep[N], f[LOG][N], dl[N], dr[N];
vector<int> G[N];
namespace SegTree {
long long add[N << 2], h[N << 2];
inline void Build(int o, int L, int R) {
  if (L == R) {
    h[o] = rw[line[L]];
    return;
  }
  Build((o << 1), L, ((L + R) >> 1));
  Build((o << 1 | 1), ((L + R) >> 1) + 1, R);
  h[o] = h[(o << 1)] + h[(o << 1 | 1)];
}
inline void Modify(int o, int L, int R, long long av, int ql, int qr) {
  if (ql > qr) return;
  if (ql <= L && qr >= R) {
    add[o] += av;
    h[o] += av * (R - L + 1);
    return;
  }
  if (ql <= ((L + R) >> 1)) Modify((o << 1), L, ((L + R) >> 1), av, ql, qr);
  if (qr > ((L + R) >> 1))
    Modify((o << 1 | 1), ((L + R) >> 1) + 1, R, av, ql, qr);
  h[o] = h[(o << 1)] + h[(o << 1 | 1)] + add[o] * (R - L + 1);
}
inline long long Query(int o, int L, int R, long long s, int ql, int qr) {
  if (ql > qr) return 0;
  if (ql <= L && qr >= R) return s * (R - L + 1) + h[o];
  long long ret = 0;
  if (ql <= ((L + R) >> 1))
    ret += Query((o << 1), L, ((L + R) >> 1), s + add[o], ql, qr);
  if (qr > ((L + R) >> 1))
    ret += Query((o << 1 | 1), ((L + R) >> 1) + 1, R, s + add[o], ql, qr);
  return ret;
}
};  // namespace SegTree
inline void Dfs(int u, int F) {
  dep[u] = dep[F] + 1;
  dl[u] = ++clk;
  f[0][u] = F;
  line[clk] = u;
  for (int j = (1); j <= (int)(19); ++j) f[j][u] = f[j - 1][f[j - 1][u]];
  for (int i = (0); i <= (int)(G[u].size() - 1); ++i) {
    int v = G[u][i];
    if (v != F) Dfs(v, u);
  }
  dr[u] = clk;
}
inline int Lca(int u, int v) {
  if (dep[u] < dep[v]) swap(u, v);
  for (int i = (Log[dep[u]]); i >= (int)(0); --i)
    if (dep[f[i][u]] >= dep[v]) u = f[i][u];
  if (u == v) return u;
  for (int i = (Log[dep[u]]); i >= (int)(0); --i)
    if (f[i][u] ^ f[i][v]) u = f[i][u], v = f[i][v];
  return f[0][u];
}
inline int Find(int u) {
  int v = rt;
  for (int i = (Log[dep[v]]); i >= (int)(0); --i)
    if (dep[f[i][v]] > dep[u]) v = f[i][v];
  return v;
}
inline long long Solve(int u, int w) {
  if (u == rt) {
    if (!w) return SegTree::h[1];
    SegTree::Modify(1, 1, n, w, 1, n);
  } else if (dl[rt] < dl[u] || dl[rt] > dr[u]) {
    if (!w) return SegTree::Query(1, 1, n, 0, dl[u], dr[u]);
    SegTree::Modify(1, 1, n, w, dl[u], dr[u]);
  } else {
    u = Find(u);
    if (!w)
      return SegTree::Query(1, 1, n, 0, 1, dl[u] - 1) +
             SegTree::Query(1, 1, n, 0, dr[u] + 1, n);
    SegTree::Modify(1, 1, n, w, 1, dl[u] - 1);
    SegTree::Modify(1, 1, n, w, dr[u] + 1, n);
  }
  return 0ll;
}
int main() {
  int op, u, v, w;
  Read(n), Read(Q);
  for (int i = (1); i <= (int)(n); ++i) Read(rw[i]);
  for (int i = (2); i <= (int)(n); ++i) Log[i] = Log[i >> 1] + 1;
  for (int i = (1); i <= (int)(n - 1); ++i) {
    Read(u), Read(v);
    G[u].push_back(v);
    G[v].push_back(u);
  }
  Dfs(rt = 1, 0);
  SegTree::Build(1, 1, n);
  while (Q--) {
    Read(op);
    if (op == 1)
      Read(rt);
    else if (op == 2) {
      Read(u), Read(v), Read(w);
      if (w == 0) continue;
      int lca, fu = Lca(u, rt), fv = Lca(v, rt);
      if (fu == fv)
        lca = Lca(u, v);
      else
        lca = dep[fu] > dep[fv] ? fu : fv;
      Solve(lca, w);
    } else {
      Read(u);
      printf("%lld\n", Solve(u, 0));
    }
  }
  return 0;
}
