#include <bits/stdc++.h>
using namespace std;
inline int qread() {
  int x = 0, sign = 1;
  char c = getchar();
  while (c < '0' || c > '9') {
    if (c == '-') sign = -1;
    c = getchar();
  }
  while (c >= '0' && c <= '9') {
    x = x * 10 + c - '0';
    c = getchar();
  }
  return x * sign;
}
int n, q;
int a[100005];
int root = 1;
struct edge {
  int from;
  int to;
  int next;
} E[100005 << 1];
int head[100005];
int size = 0;
void add_edge(int u, int v) {
  size++;
  E[size].from = u;
  E[size].to = v;
  E[size].next = head[u];
  head[u] = size;
}
int cnt;
int log2n;
int l[100005], r[100005];
int deep[100005], anc[100005][32];
void dfs(int x, int fa) {
  l[x] = ++cnt;
  anc[x][0] = fa;
  for (int i = 1; i <= log2n; i++) {
    anc[x][i] = anc[anc[x][i - 1]][i - 1];
  }
  for (int i = head[x]; i; i = E[i].next) {
    int y = E[i].to;
    if (y != fa) {
      deep[y] = deep[x] + 1;
      dfs(y, x);
    }
  }
  r[x] = cnt;
}
int lca(int x, int y) {
  if (deep[x] < deep[y]) swap(x, y);
  for (int i = log2n; i >= 0; i--) {
    if (deep[anc[x][i]] >= deep[y]) {
      x = anc[x][i];
    }
  }
  if (x == y) return x;
  for (int i = log2n; i >= 0; i--) {
    if (anc[x][i] != anc[y][i]) {
      x = anc[x][i];
      y = anc[y][i];
    }
  }
  return anc[x][0];
}
int tri_lca(int u, int v, int r) {
  int l1 = lca(u, v);
  int l2 = lca(u, r);
  int l3 = lca(v, r);
  int max_deep = max(deep[l1], max(deep[l2], deep[l3]));
  if (deep[l1] == max_deep)
    return l1;
  else if (deep[l2] == max_deep)
    return l2;
  else
    return l3;
}
int get_close(int w, int r) {
  int x = r;
  for (int i = log2n; i >= 0; i--) {
    if (deep[anc[x][i]] > deep[w]) {
      x = anc[x][i];
    }
  }
  return x;
}
struct node {
  int l;
  int r;
  long long v;
  long long mark;
  int len() { return r - l + 1; }
} tree[100005 << 2];
void push_up(int pos) { tree[pos].v = tree[pos << 1].v + tree[pos << 1 | 1].v; }
void build(int l, int r, int pos) {
  tree[pos].l = l;
  tree[pos].r = r;
  tree[pos].v = 0;
  tree[pos].mark = 0;
  if (l == r) return;
  int mid = (l + r) >> 1;
  build(l, mid, pos << 1);
  build(mid + 1, r, pos << 1 | 1);
}
void push_down(int pos) {
  if (tree[pos].mark) {
    tree[pos << 1].mark += tree[pos].mark;
    tree[pos << 1 | 1].mark += tree[pos].mark;
    tree[pos << 1].v += tree[pos].mark * tree[pos << 1].len();
    tree[pos << 1 | 1].v += tree[pos].mark * tree[pos << 1 | 1].len();
    tree[pos].mark = 0;
  }
}
void update(int L, int R, long long v, int pos) {
  if (L <= tree[pos].l && R >= tree[pos].r) {
    tree[pos].mark += v;
    tree[pos].v += (v * tree[pos].len());
    return;
  }
  push_down(pos);
  int mid = (tree[pos].l + tree[pos].r) >> 1;
  if (L <= mid) update(L, R, v, pos << 1);
  if (R > mid) update(L, R, v, pos << 1 | 1);
  push_up(pos);
}
long long query(int L, int R, int pos) {
  if (L <= tree[pos].l && R >= tree[pos].r) {
    return tree[pos].v;
  }
  push_down(pos);
  int mid = (tree[pos].l + tree[pos].r) >> 1;
  long long ans = 0;
  if (L <= mid) ans += query(L, R, pos << 1);
  if (R > mid) ans += query(L, R, pos << 1 | 1);
  return ans;
}
void change(int u, int v, int x) {
  int xx = lca(u, v);
  int lca_num = tri_lca(u, v, root);
  if (l[root] < l[xx] || r[root] > r[xx]) {
    update(l[xx], r[xx], x, 1);
    return;
  } else if (lca_num == root) {
    update(1, n, x, 1);
    return;
  } else {
    int w2 = get_close(lca_num, root);
    update(1, n, x, 1);
    update(l[w2], r[w2], -x, 1);
    return;
  }
}
long long sum(int w) {
  if (l[root] < l[w] || r[root] > r[w]) {
    return query(l[w], r[w], 1);
  } else {
    if (w == root) {
      return query(1, n, 1);
    }
    int sonw = get_close(w, root);
    return query(1, n, 1) - query(l[sonw], r[sonw], 1);
  }
}
int main() {
  int u, v, cmd, x;
  n = qread();
  q = qread();
  for (int i = 1; i <= n; i++) a[i] = qread();
  for (int i = 1; i < n; i++) {
    u = qread();
    v = qread();
    add_edge(u, v);
    add_edge(v, u);
  }
  deep[1] = 1;
  log2n = log2(n) + 1;
  dfs(1, 0);
  build(1, n, 1);
  for (int i = 1; i <= n; i++) {
    update(l[i], l[i], a[i], 1);
  }
  for (int i = 1; i <= q; i++) {
    cmd = qread();
    if (cmd == 1) {
      v = qread();
      root = v;
    } else if (cmd == 2) {
      u = qread();
      v = qread();
      x = qread();
      change(u, v, x);
    } else {
      v = qread();
      printf("%I64d\n", sum(v));
    }
  }
  return 0;
}
