#include <bits/stdc++.h>
using namespace std;
struct node {
  int l, r, mid;
  long long sum, tg;
} tre[250005 * 4];
long long val[250005 * 4], vals[250005 * 4];
long long dp[250005 * 4][21];
long long du[250005 * 4];
long long dfn[250005 * 4][2];
vector<int> vec[250005 * 4];
long long n, m, u, v, rt, t = 0, x, od, ans;
inline long long read() {
  long long x = 0, f = 1;
  char c = getchar();
  while (c > '9' || c < '0') {
    if (c == '-') f = -1;
    c = getchar();
  }
  while (c >= '0' && c <= '9') {
    x = x * 10 + c - '0';
    c = getchar();
  }
  return x * f;
}
void dfs(long long x, long long d, long long fa) {
  du[x] = d;
  t++;
  dfn[x][0] = t;
  dp[x][0] = fa;
  for (int i = 1; i <= 20; i++) {
    dp[x][i] = dp[dp[x][i - 1]][i - 1];
  }
  for (int i = 0; i <= (int)vec[x].size() - 1; i++) {
    if (vec[x][i] != fa) {
      dfs(vec[x][i], d + 1, x);
    }
  }
  t++;
  dfn[x][1] = t;
  return;
}
long long build(long long x, long long l, long long r) {
  tre[x].l = l;
  tre[x].r = r;
  tre[x].mid = (l + r) >> 1;
  if (l == r) {
    return tre[x].sum = vals[l];
  } else {
    return tre[x].sum = build(x * 2, tre[x].l, tre[x].mid) +
                        build(x * 2 + 1, tre[x].mid + 1, tre[x].r);
  }
}
void add(long long x, long long l, long long r, long long y) {
  tre[x].sum += y * (r - l + 1);
  if (tre[x].l == l && tre[x].r == r) {
    tre[x].tg += y;
  } else {
    if (l <= tre[x].mid && r > tre[x].mid) {
      add(x * 2, l, tre[x].mid, y);
      add(x * 2 + 1, tre[x].mid + 1, r, y);
    } else {
      if (r <= tre[x].mid) {
        add(x * 2, l, r, y);
      } else {
        add(x * 2 + 1, l, r, y);
      }
    }
  }
}
long long ask(long long x, long long l, long long r) {
  if (l == tre[x].l && r == tre[x].r) {
    return tre[x].sum;
  } else {
    if (tre[x].tg) {
      add(x * 2, tre[x].l, tre[x].mid, tre[x].tg);
      add(x * 2 + 1, tre[x].mid + 1, tre[x].r, tre[x].tg);
      tre[x].tg = 0;
    }
    if (l <= tre[x].mid && r > tre[x].mid) {
      return ask(x * 2, l, tre[x].mid) + ask(x * 2 + 1, tre[x].mid + 1, r);
    } else {
      if (r <= tre[x].mid) {
        return ask(x * 2, l, r);
      } else {
        return ask(x * 2 + 1, l, r);
      }
    }
  }
}
long long lca(long long u, long long v) {
  if (du[u] > du[v]) swap(u, v);
  for (int i = 19; i >= 0; i--) {
    if (du[dp[v][i]] >= du[u]) {
      v = dp[v][i];
    }
  }
  if (u == v) return u;
  for (int i = 19; i >= 0; i--) {
    if (dp[u][i] != dp[v][i]) {
      u = dp[u][i];
      v = dp[v][i];
    }
  }
  return dp[u][0];
}
void adds(long long x, long long y) { add(1, dfn[x][0], dfn[x][1], y); }
long long asks(long long x) { return ask(1, dfn[x][0], dfn[x][1]) / 2; }
long long askc(long long x, long long y) {
  for (int i = 19; i >= 0; i--) {
    if (du[dp[x][i]] >= y) {
      x = dp[x][i];
    }
  }
  return x;
}
int main() {
  long long l2, l1;
  n = read(), m = read();
  for (int i = 1; i <= n; i++) {
    val[i] = read();
  }
  for (int i = 1; i <= n - 1; i++) {
    u = read(), v = read();
    vec[u].push_back(v);
    vec[v].push_back(u);
  }
  dfs(1, 1, 0);
  for (int i = 1; i <= n; i++) {
    vals[dfn[i][0]] = vals[dfn[i][1]] = val[i];
  }
  build(1, 1, 2 * n);
  rt = 1;
  while (m--) {
    od = read();
    if (od == 1) {
      u = read();
      rt = u;
    } else if (od == 2) {
      u = read(), v = read(), x = read();
      l2 = lca(u, v);
      l1 = lca(l2, rt);
      if (l1 == l2) {
        adds(1, x);
        l1 = max(du[lca(u, rt)], du[lca(v, rt)]);
        if (du[rt] != l1) {
          adds(askc(rt, l1 + 1), -x);
        }
      } else
        adds(l2, x);
    } else {
      u = read();
      l2 = lca(u, rt);
      if (u == l2) {
        if (u == rt) {
          ans = asks(1);
          cout << ans << endl;
        } else {
          ans = asks(1) - asks(askc(rt, du[u] + 1));
          cout << ans << endl;
        }
      } else {
        ans = asks(u);
        cout << ans << endl;
      }
    }
  }
  return 0;
}
