#include <bits/stdc++.h>
using namespace std;
const long long arr = 2e5 + 100;
vector<long long> vec[arr];
long long deep[arr], dp[arr][25], v[8 * arr], push[8 * arr], in[arr], out[arr];
long long now_root = 1;
long long cnt = 0;
void make_push(long long i, long long tl, long long tr) {
  push[i * 2] += push[i];
  push[i * 2 + 1] += push[i];
  long long d = (tl + tr) / 2;
  v[i * 2] += push[i] * (d - tl + 1);
  v[i * 2 + 1] += push[i] * (tr - d);
  push[i] = 0;
}
void change(long long i, long long tl, long long tr, long long l, long long r,
            long long x) {
  if (tl >= l && tr <= r) {
    v[i] += x * (tr - tl + 1);
    push[i] += x;
    return;
  }
  if (tl > r || tr < l) return;
  long long d = (tl + tr) / 2;
  make_push(i, tl, tr);
  change(i * 2, tl, d, l, r, x);
  change(i * 2 + 1, d + 1, tr, l, r, x);
  v[i] = v[i * 2] + v[i * 2 + 1];
}
long long get(long long i, long long tl, long long tr, long long l,
              long long r) {
  if (tl >= l && tr <= r) return (v[i]);
  if (tl > r || tr < l) return (0);
  long long d = (tl + tr) / 2;
  make_push(i, tl, tr);
  return (get(i * 2, tl, d, l, r) + get(i * 2 + 1, d + 1, tr, l, r));
}
void dfs(long long u, long long pred) {
  in[u] = ++cnt;
  deep[u] = deep[pred] + 1;
  dp[u][0] = pred;
  for (long long i = 1; i <= 20; i++) dp[u][i] = dp[dp[u][i - 1]][i - 1];
  for (auto i : vec[u])
    if (i != pred) dfs(i, u);
  out[u] = cnt;
}
long long lca(long long a, long long b) {
  for (long long i = 20; i >= 0; i--)
    if (deep[a] - (1 << i) >= deep[b]) a = dp[a][i];
  for (long long i = 20; i >= 0; i--)
    if (deep[b] - (1 << i) >= deep[a]) b = dp[b][i];
  for (long long i = 20; i >= 0; i--)
    if (dp[a][i] != dp[b][i]) {
      a = dp[a][i];
      b = dp[b][i];
    }
  if (a == b) return (a);
  return (dp[a][0]);
}
long long real_lca(long long a, long long b) {
  long long intree = 0;
  if (lca(a, now_root) == now_root) intree++;
  if (lca(b, now_root) == now_root) intree++;
  if (intree == 2) return (lca(a, b));
  if (intree == 1) return (now_root);
  long long x = lca(a, now_root);
  long long y = lca(b, now_root);
  long long z = lca(a, b);
  if (deep[x] < deep[y]) swap(x, y);
  if (deep[x] < deep[z]) swap(x, z);
  if (deep[x] == deep[y] && x != y) exit(1);
  if (deep[x] == deep[z] && x != z) exit(1);
  return (x);
}
long long plca(long long a, long long b) {
  for (long long i = 20; i >= 0; i--)
    if (deep[a] - (1 << i) > deep[b]) a = dp[a][i];
  return (a);
}
long long a[arr];
signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  ;
  long long n, q;
  cin >> n >> q;
  for (long long i = 1; i <= n; i++) cin >> a[i];
  for (long long i = 1; i < n; i++) {
    long long a, b;
    cin >> a >> b;
    vec[a].push_back(b);
    vec[b].push_back(a);
  }
  dfs(1, 0);
  for (long long i = 1; i <= n; i++) {
    change(1, 1, n, in[i], in[i], a[i]);
  }
  while (q--) {
    long long type;
    cin >> type;
    if (type == 1) {
      cin >> now_root;
    } else if (type == 2) {
      long long u, uu, x;
      cin >> u >> uu >> x;
      u = real_lca(u, uu);
      if (u == now_root)
        change(1, 1, n, 1, n, x);
      else if (lca(u, now_root) == u) {
        change(1, 1, n, 1, n, x);
        long long pc = plca(now_root, u);
        change(1, 1, n, in[pc], out[pc], -x);
      } else {
        change(1, 1, n, in[u], out[u], x);
      }
    } else {
      long long u, x;
      cin >> u;
      long long ans = 0;
      if (u == now_root)
        ans += get(1, 1, n, 1, n);
      else if (lca(u, now_root) == u) {
        ans += get(1, 1, n, 1, n);
        long long pc = plca(now_root, u);
        ans -= get(1, 1, n, in[pc], out[pc]);
      } else {
        ans += get(1, 1, n, in[u], out[u]);
      }
      cout << ans << '\n';
    }
  }
}
