#include <bits/stdc++.h>
using namespace std;
template <class T>
bool umin(T& a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T>
bool umax(T& a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
int in[100009], out[100009], TIM, id[100009];
int P[100009][19], lvl[100009], n, arr[100009], q;
long long s[100009 << 2], lazy[100009 << 2];
vector<int> adj[100009];
void dfs(int nd, int pr) {
  in[nd] = ++TIM;
  id[TIM] = nd;
  lvl[nd] = (~pr ? lvl[pr] + 1 : 1);
  P[nd][0] = pr;
  for (int i = 0; i < int(adj[nd].size()); i++) {
    int to = adj[nd][i];
    if (to == pr) continue;
    dfs(to, nd);
  }
  out[nd] = TIM;
}
void create() {
  for (int j = 1; j <= 17; j++)
    for (int i = 1; i <= n; i++) {
      if (~P[i][j - 1]) P[i][j] = P[P[i][j - 1]][j - 1];
    }
}
int LCA(int x, int y) {
  if (lvl[x] < lvl[y]) swap(x, y);
  for (int i = 17; i >= 0; i--)
    if (lvl[x] - (1 << i) >= lvl[y]) x = P[x][i];
  if (x == y) return x;
  for (int i = 17; i >= 0; i--)
    if (~P[x][i] and P[x][i] != P[y][i]) x = P[x][i], y = P[y][i];
  return P[x][0];
}
void build(int nd, int x, int y) {
  if (x == y) {
    s[nd] = arr[id[x]];
    return;
  }
  int mid = (x + y) >> 1;
  build(nd << 1, x, mid);
  build(nd << 1 | 1, mid + 1, y);
  s[nd] = s[nd << 1] + s[nd << 1 | 1];
}
void shift(int nd, int x, int y) {
  long long& ret = lazy[nd];
  if (!ret) return;
  int mid = (x + y) >> 1;
  lazy[nd << 1] += ret;
  s[nd << 1] += (mid - x + 1) * 1LL * ret;
  lazy[nd << 1 | 1] += ret;
  s[nd << 1 | 1] += (y - mid) * 1LL * ret;
  ret = 0;
}
void inc(int l, int r, int v, int nd, int x, int y) {
  if (l > y or x > r) return;
  if (l <= x and y <= r) {
    s[nd] += (y - x + 1) * 1LL * v;
    lazy[nd] += v;
    return;
  }
  shift(nd, x, y);
  int mid = (x + y) >> 1;
  inc(l, r, v, nd << 1, x, mid);
  inc(l, r, v, nd << 1 | 1, mid + 1, y);
  s[nd] = s[nd << 1] + s[nd << 1 | 1];
}
int jump(int x, int y) {
  for (int i = 17; i >= 0; i--)
    if (lvl[x] - (1 << i) > lvl[y]) x = P[x][i];
  return x;
}
long long tap(int l, int r, int nd, int x, int y) {
  if (l > y or x > r) return 0;
  if (l <= x and y <= r) return s[nd];
  shift(nd, x, y);
  int mid = (x + y) >> 1;
  return tap(l, r, nd << 1, x, mid) + tap(l, r, nd << 1 | 1, mid + 1, y);
}
int main() {
  memset(P, -1, sizeof P);
  scanf("%d%d", &n, &q);
  for (int i = 1; i <= n; i++) scanf("%d", arr + i);
  for (int i = 1; i < n; i++) {
    int u, v;
    scanf("%d%d", &u, &v);
    adj[u].push_back(v);
    adj[v].push_back(u);
  }
  dfs(1, -1);
  build(1, 1, n);
  create();
  int root = 1;
  while (q--) {
    int t;
    scanf("%d", &t);
    if (t == 1) {
      int v;
      scanf("%d", &v);
      root = v;
    } else if (t == 2) {
      int u, v, x;
      scanf("%d%d%d", &u, &v, &x);
      int nd = LCA(u, v);
      if (in[nd] <= in[root] and out[root] <= out[nd]) {
        int a = LCA(root, u);
        int b = LCA(root, v);
        int c = a;
        if (lvl[a] < lvl[b]) c = b;
        if (c == root)
          inc(1, n, x, 1, 1, n);
        else {
          int node = jump(root, c);
          inc(1, in[node] - 1, x, 1, 1, n);
          inc(out[node] + 1, n, x, 1, 1, n);
        }
      } else {
        inc(in[nd], out[nd], x, 1, 1, n);
      }
    } else {
      int v;
      scanf("%d", &v);
      if (in[v] <= in[root] and out[root] <= out[v]) {
        if (v == root)
          printf("%lld\n", s[1]);
        else {
          int node = jump(root, v);
          printf("%lld\n", tap(1, in[node] - 1, 1, 1, n) +
                               tap(out[node] + 1, n, 1, 1, n));
        }
      } else
        printf("%lld\n", tap(in[v], out[v], 1, 1, n));
    }
  }
  return 0;
}
