#include <bits/stdc++.h>
using namespace std;
const int INF = (int)2e9 + 10;
const int mod = (int)1e9 + 7;
const int N = (int)1e6 + 10;
const long long LLINF = (long long)1e18 + 10;
const long double pi = acos(-1.0);
const long double eps = (long double)1e-10;
template <typename T1, typename T2>
bool umin(T1 &x, const T2 &y) {
  if (x > y) return x = y, true;
  return false;
}
template <typename T1, typename T2>
bool umax(T1 &x, const T2 &y) {
  if (x < y) return x = y, true;
  return false;
}
template <typename T>
T getint() {
  char c = getchar();
  T p = 1, x = 0;
  while (c == ' ' || c == '\n') c = getchar();
  if (c == '-') p = -1, c = getchar();
  while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
  return x * p;
}
int n;
vector<int> g[N];
int r = 1;
int sp[20][N];
int le[N], ri[N], d[N];
vector<int> order;
int a[N];
void dfs(int v, int p) {
  sp[0][v] = p;
  le[v] = order.size();
  order.push_back(v);
  for (auto u : g[v]) {
    if (u != p) {
      d[u] = d[v] + 1;
      dfs(u, v);
    }
  }
  ri[v] = order.size() - 1;
}
void build() {
  for (int i = 1; i < 20; ++i) {
    for (int j = 1; j <= n; ++j) {
      sp[i][j] = sp[i - 1][sp[i - 1][j]];
    }
  }
}
int lca(int u, int v) {
  if (d[u] < d[v]) swap(u, v);
  for (int i = 19; i >= 0; --i) {
    if (d[u] - (1 << i) >= d[v]) u = sp[i][u];
  }
  if (u == v) return u;
  for (int i = 19; i >= 0; --i) {
    if (sp[i][u] != sp[i][v]) u = sp[i][u], v = sp[i][v];
  }
  return sp[0][u];
}
int par(int v, int r) {
  if (le[r] <= le[v] || ri[v] < le[r]) return -1;
  for (int i = 19; i >= 0; --i) {
    if (d[r] - (1 << i) > d[v]) r = sp[i][r];
  }
  return r;
}
struct tree {
  long long sum = 0;
  long long push = 0;
  int tl, tr;
  tree *le, *ri;
  tree(int l, int r) {
    tl = l;
    tr = r;
    sum = 0;
    push = 0;
    if (l == r) {
      sum = a[order[l]];
      le = ri = NULL;
      return;
    }
    le = new tree(l, (l + r) / 2);
    ri = new tree((l + r) / 2 + 1, r);
    sum = le->sum + ri->sum;
  }
  void push_up() {
    le->sum += 1ll * (le->tr - le->tl + 1) * push;
    ri->sum += 1ll * (ri->tr - ri->tl + 1) * push;
    le->push += push;
    ri->push += push;
    push = 0;
  }
  void add(int l, int r, int x) {
    if (r < tl || tr < l) return;
    if (l <= tl && tr <= r) {
      push += x;
      sum += 1ll * (tr - tl + 1) * x;
      return;
    }
    push_up();
    le->add(l, r, x);
    ri->add(l, r, x);
    sum = le->sum + ri->sum;
  }
  long long get(int l, int r) {
    if (r < tl || tr < l) return 0;
    if (l <= tl && tr <= r) return sum;
    push_up();
    return le->get(l, r) + ri->get(l, r);
  }
};
bool is(int v, int u) {
  if (le[v] <= le[u] && le[u] <= ri[v]) return true;
  return false;
}
int main() {
  srand(time(NULL));
  ios_base::sync_with_stdio(0);
  int q;
  cin >> n >> q;
  for (int i = 1; i <= n; ++i) {
    cin >> a[i];
  }
  for (int i = 1; i < n; ++i) {
    int x, y;
    cin >> x >> y;
    g[x].push_back(y);
    g[y].push_back(x);
  }
  dfs(1, 1);
  build();
  tree *t = new tree(0, n - 1);
  while (q--) {
    int type;
    cin >> type;
    if (type == 1) {
      cin >> r;
    }
    if (type == 2) {
      int u, v, x;
      cin >> u >> v >> x;
      int l = lca(u, v);
      if (l == r || (is(l, r) && (is(r, v) || is(r, u)))) {
        t->add(0, n - 1, x);
        continue;
      }
      if (is(l, r)) {
        int to;
        int l1 = lca(r, u);
        int l2 = lca(r, v);
        if (d[l1] > d[l2])
          to = par(l1, r);
        else
          to = par(l2, r);
        t->add(0, n - 1, x);
        t->add(le[to], ri[to], -x);
        continue;
      }
      t->add(le[l], ri[l], x);
    }
    if (type == 3) {
      int v;
      cin >> v;
      if (v == r) {
        cout << t->get(0, n - 1) << '\n';
        continue;
      }
      int to = par(v, r);
      if (to == -1) {
        cout << t->get(le[v], ri[v]) << '\n';
      } else {
        cout << t->get(0, n - 1) - t->get(le[to], ri[to]) << '\n';
      }
    }
  }
  return 0;
}
