#include <bits/stdc++.h>
using namespace std;
int n, m, tot, idx, root = 1;
int now[100005], val[100005], pre[100005 * 2], son[100005 * 2], dep[100005],
    l[100005], r[100005], v[100005];
int Log[100005], f[100005][20];
inline int read() {
  int x = 0, f = 1;
  char ch = getchar();
  for (; ch < '0' || ch > '9'; ch = getchar())
    if (ch == '-') f = -1;
  for (; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
  return x * f;
}
void add(int a, int b) { son[++tot] = b, pre[tot] = now[a], now[a] = tot; }
void link(int a, int b) { add(a, b), add(b, a); }
void dfs(int x, int fa) {
  l[x] = ++idx, v[idx] = val[x];
  dep[x] = dep[fa] + 1;
  for (int i = 1; i <= Log[dep[x]]; i++) f[x][i] = f[f[x][i - 1]][i - 1];
  for (int p = now[x]; p; p = pre[p])
    if (son[p] != fa) f[son[p]][0] = x, dfs(son[p], x);
  r[x] = idx;
}
int calc_lca(int a, int b) {
  if (dep[a] < dep[b]) swap(a, b);
  int x = dep[a] - dep[b], t = 0;
  for (; x; x >>= 1, ++t)
    if (x & 1) a = f[a][t];
  if (a == b) return a;
  t = Log[dep[a]];
  while (f[a][0] != f[b][0]) {
    while (f[a][t] == f[b][t]) --t;
    a = f[a][t], b = f[b][t];
  }
  return f[a][0];
}
struct segment_tree {
  struct tree_node {
    int size;
    long long sum, tag;
  } tree[100005 * 4];
  void update(int p) { tree[p].sum = tree[p << 1].sum + tree[p << 1 | 1].sum; }
  void build(int p, int l, int r) {
    tree[p].size = r - l + 1;
    if (l == r) {
      tree[p].sum = v[l];
      return;
    }
    int mid = (l + r) >> 1;
    build(p << 1, l, mid), build(p << 1 | 1, mid + 1, r);
    update(p);
  }
  void add_tag(int p, long long v) {
    tree[p].sum += 1ll * tree[p].size * v, tree[p].tag += v;
  }
  void push_down(int p) {
    if (!tree[p].tag) return;
    long long &v = tree[p].tag;
    add_tag(p << 1, v), add_tag(p << 1 | 1, v), v = 0;
  }
  void change(int p, int l, int r, int x, int y, int v) {
    if (x > y) return;
    if (x <= l && r <= y) {
      add_tag(p, v);
      return;
    }
    int mid = (l + r) >> 1;
    push_down(p);
    if (x <= mid) change(p << 1, l, mid, x, y, v);
    if (y > mid) change(p << 1 | 1, mid + 1, r, x, y, v);
    update(p);
  }
  long long query(int p, int l, int r, int x, int y) {
    if (x > y) return 0;
    if (x <= l && r <= y) return tree[p].sum;
    int mid = (l + r) >> 1;
    long long ret = 0;
    push_down(p);
    if (x <= mid) ret += query(p << 1, l, mid, x, y);
    if (y > mid) ret += query(p << 1 | 1, mid + 1, r, x, y);
    return ret;
  }
} T;
struct node {
  int x, y, z;
  node() {}
  node(int _x, int _y, int _z) { x = _x, y = _y, z = _z; }
};
node get_subtree(int x) {
  if (x == root) return node(1, n, 1);
  if (l[root] < l[x] || r[root] > r[x]) return node(l[x], r[x], 1);
  int y = root;
  for (int i = Log[dep[y]]; ~i; i--)
    if (dep[f[y][i]] > dep[x]) y = f[y][i];
  return node(l[y], r[y], -1);
}
void change(int x, int v) {
  node pp = get_subtree(x);
  if (!x) cerr << pp.x << ' ' << pp.y << ' ' << pp.z << endl;
  if (~pp.z)
    T.change(1, 1, n, pp.x, pp.y, v);
  else
    T.change(1, 1, n, 1, pp.x - 1, v), T.change(1, 1, n, pp.y + 1, n, v);
}
void query(int x) {
  node pp = get_subtree(x);
  if (~pp.z)
    printf("%lld\n", T.query(1, 1, n, pp.x, pp.y));
  else
    printf("%lld\n",
           T.query(1, 1, n, 1, pp.x - 1) + T.query(1, 1, n, pp.y + 1, n));
}
void solve_lca(int x, int y, int v) {
  if (x == y) {
    change(x, v);
    return;
  }
  int lca = calc_lca(x, y);
  if (l[root] < l[lca] || l[root] > r[lca] || lca == root) {
    change(lca, v);
    return;
  }
  if (x != lca && l[root] >= l[x] && l[root] <= r[x]) {
    change(x, v);
    return;
  }
  for (int i = Log[dep[x]]; ~i; i--)
    if (f[x][i] && (l[root] < l[f[x][i]] || l[root] > r[f[x][i]])) x = f[x][i];
  x = f[x][0];
  if (dep[x] > dep[lca]) {
    change(x, v);
    return;
  }
  if (l[root] >= l[y] && l[root] <= r[y]) {
    change(y, v);
    return;
  }
  for (int i = Log[dep[y]]; ~i; i--)
    if (f[y][i] && (l[root] < l[f[y][i]] || l[root] > r[f[y][i]])) y = f[y][i];
  y = f[y][0];
  change(y, v);
}
int main() {
  n = read(), m = read();
  for (int i = 2; i <= n; i++) Log[i] = Log[i >> 1] + 1;
  for (int i = 1; i <= n; i++) val[i] = read();
  for (int i = 1, x, y; i < n; i++) x = read(), y = read(), link(x, y);
  dfs(1, 0);
  T.build(1, 1, n);
  while (m--) {
    int op = read();
    if (op == 1)
      root = read();
    else if (op == 2) {
      int x = read(), y = read(), v = read();
      solve_lca(x, y, v);
    } else if (op == 3) {
      int x = read();
      query(x);
    }
  }
  return 0;
}
