#include <bits/stdc++.h>
using namespace std;
namespace IO {
const int L = 1 << 18;
char ibuf[L | 1], *iS = ibuf, *iT = ibuf;
char obuf[L | 1], *oS = obuf, *oT = obuf + L;
char c, st[66];
int tp = 0;
inline char gc() {
  if (iS == iT) iT = (iS = ibuf) + fread(ibuf, sizeof(char), L, stdin);
  return (*iS++);
}
inline void flush() {
  fwrite(obuf, sizeof(char), oS - obuf, stdout);
  oS = obuf;
}
inline void pc(char c) {
  *oS++ = c;
  if (oS == oT) flush();
}
inline long long read() {
  long long x = 0;
  bool f = 0;
  c = gc();
  for (; !isdigit(c); c = gc()) {
    if (c == '-') f = 1;
  }
  for (; isdigit(c); c = gc()) x = (x << 1) + (x << 3) + (c & 15);
  return f ? -x : x;
}
void write(long long x) {
  if (!x) pc('0');
  while (x) st[++tp] = x % 10 + '0', x /= 10;
  while (tp) pc(st[tp--]);
}
void writeln(long long x) {
  if (x < 0) {
    x = -x, pc('-');
  }
  write(x);
  pc('\n');
}
struct IOflusher {
  ~IOflusher() { flush(); }
} _ioflusher_;
}  // namespace IO
using IO::read;
using IO::writeln;
struct xbk {
  int ed, nx;
} e[(1000010)];
struct xll {
  long long l, r;
  long long sum, tag;
};
struct zxy {
  int l, r;
} a[(500010)];
int n, Q, cnt, rt, t = 20, tot = 0;
int dfn[(500010)], head[(500010)], ff[(500010)][22], dep[(500010)],
    fa[(500010)], sz[(500010)];
long long val[(500010)], w[(1000010)];
struct Tree {
  xll t[(4000010)];
  inline void spread(int p) {
    if (t[p].tag == 0) return;
    t[p << 1].sum += (t[p << 1].r - t[p << 1].l + 1) * t[p].tag;
    t[p << 1 | 1].sum += (t[p << 1 | 1].r - t[p << 1 | 1].l + 1) * t[p].tag;
    t[p << 1].tag += t[p].tag;
    t[p << 1 | 1].tag += t[p].tag;
    t[p].tag = 0;
    return;
  }
  inline void build(int p, long long l, long long r) {
    t[p].l = l, t[p].r = r, t[p].tag = 0;
    if (l == r) {
      t[p].sum = w[l];
      return;
    }
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    t[p].sum = t[p << 1].sum + t[p << 1 | 1].sum;
    return;
  }
  inline void change(int p, long long l, long long r, long long v) {
    if (l <= t[p].l && r >= t[p].r) {
      t[p].sum += v * (t[p].r - t[p].l + 1);
      t[p].tag += v;
      return;
    }
    spread(p);
    int mid = (t[p].l + t[p].r) >> 1;
    if (l <= mid) change(p << 1, l, r, v);
    if (r > mid) change(p << 1 | 1, l, r, v);
    t[p].sum = t[p << 1].sum + t[p << 1 | 1].sum;
    return;
  }
  inline long long ask(int p, long long l, long long r) {
    if (t[p].l >= l && t[p].r <= r) return t[p].sum;
    spread(p);
    int mid = (t[p].l + t[p].r) >> 1;
    long long res = 0;
    if (l <= mid) res += ask(p << 1, l, r);
    if (r > mid) res += ask(p << 1 | 1, l, r);
    return res;
  }
} T;
inline void add(int a, int b) {
  e[++cnt].ed = b;
  e[cnt].nx = head[a];
  head[a] = cnt;
}
inline int LCA(int a, int b) {
  if (dep[a] > dep[b]) swap(a, b);
  for (int i = t; i >= 0; i--)
    if (dep[ff[b][i]] >= dep[a]) b = ff[b][i];
  if (a == b) return a;
  for (int i = t; i >= 0; i--)
    if (ff[a][i] != ff[b][i]) a = ff[a][i], b = ff[b][i];
  return ff[a][0];
}
inline void dfs(int st, int f) {
  dep[st] = dep[f] + 1, fa[st] = f, ff[st][0] = f;
  dfn[++tot] = st, a[st].l = tot;
  w[tot] = val[st];
  for (int i = 1; i <= t; i++) ff[st][i] = ff[ff[st][i - 1]][i - 1];
  for (int i = head[st]; i; i = e[i].nx) {
    int ed = e[i].ed;
    if (ed == f) continue;
    dfs(ed, st);
  }
  dfn[++tot] = st;
  w[tot] = val[st];
  a[st].r = tot;
  return;
}
inline int getfa(int st, int fff) {
  for (int i = t; i >= 0; i--)
    if (dep[ff[st][i]] > dep[fff]) st = ff[st][i];
  while (dep[fa[st]] > dep[fff]) st = fa[st];
  return st;
}
int main() {
  n = read(), Q = read();
  for (int i = 1; i <= n; i++) val[i] = read();
  for (int i = 1; i < n; i++) {
    int u = read(), v = read();
    add(u, v), add(v, u);
  }
  dfs(rt = 1, 0);
  T.build(1, 1, tot);
  while (Q--) {
    int opt = read();
    if (opt == 1) rt = read();
    if (opt == 2) {
      int u = read(), v = read();
      long long d = read();
      int l1 = LCA(u, v), l2 = LCA(v, rt), l3 = LCA(u, rt), lca;
      if (dep[l1] > dep[l2] && dep[l1] > dep[l3])
        lca = l1;
      else if (dep[l2] > dep[l1] && dep[l2] > dep[l3])
        lca = l2;
      else if (dep[l3] > dep[l2] && dep[l3] > dep[l1])
        lca = l3;
      else if (l1 == l2 && l1 == l3)
        lca = l1;
      if (a[lca].l < a[rt].l && a[lca].r > a[rt].r) {
        int ed = getfa(rt, lca);
        T.change(1, 1, tot, d);
        T.change(1, a[ed].l, a[ed].r, -d);
      } else if (lca == rt)
        T.change(1, 1, tot, d);
      else
        T.change(1, a[lca].l, a[lca].r, d);
    }
    if (opt == 3) {
      int u = read();
      if (u == rt)
        writeln(T.ask(1, a[1].l, a[1].r) >> 1);
      else if (a[u].l < a[rt].l && a[u].r > a[rt].r) {
        int ed = getfa(rt, u);
        writeln((T.ask(1, 1, tot) - T.ask(1, a[ed].l, a[ed].r)) >> 1);
      } else
        writeln(T.ask(1, a[u].l, a[u].r) >> 1);
    }
  }
  return 0;
}
