#include <bits/stdc++.h>
using namespace std;
void minimiza(pair<int, int> &a, pair<int, int> b) { a = min(a, b); }
const int tope = 1 << 20;
const int primero = 1 << 19;
const int limite = 1000000;
pair<int, int> minimo[tope];
void inserta(int pos, pair<int, int> val) {
  pos += primero;
  minimo[pos] = val;
  while (pos > 1) {
    pos /= 2;
    minimo[pos] = min(minimo[2 * pos], minimo[2 * pos + 1]);
  }
}
int minimoentre(int pos0, int pos1) {
  pos0 += primero;
  pos1 += primero;
  if (pos0 > pos1) swap(pos0, pos1);
  if (pos0 == pos1) return minimo[pos0].second;
  pair<int, int> mini = min(minimo[pos0], minimo[pos1]);
  while (pos0 + 1 < pos1) {
    if (pos0 % 2 == 0) minimiza(mini, minimo[pos0 + 1]);
    pos0 /= 2;
    if (pos1 % 2 == 1) minimiza(mini, minimo[pos1 - 1]);
    pos1 /= 2;
  }
  return mini.second;
}
int getancestro(int pos, int prof) {
  pos += primero;
  if (minimo[pos].first == prof) return minimo[pos].second;
  for (;;) {
    if (pos % 2 == 1 and minimo[pos - 1].first <= prof) {
      pos--;
      while (pos < primero)
        if (minimo[2 * pos + 1].first <= prof)
          pos = 2 * pos + 1;
        else
          pos = 2 * pos;
      return minimo[pos].second;
    }
    pos /= 2;
  }
  return 0;
}
long long int suma[tope];
long long int anyade[tope];
long long int cuantos[tope];
void recalcula(int pos) {
  suma[pos] = suma[2 * pos] + anyade[2 * pos] * cuantos[2 * pos] +
              suma[2 * pos + 1] + anyade[2 * pos + 1] * cuantos[2 * pos + 1];
}
void anyadeentre(int pos0, int pos1, long long int val) {
  pos0 += primero;
  pos1 += primero;
  if (pos0 > pos1) return;
  if (pos0 == pos1) {
    anyade[pos0] += val;
  } else {
    anyade[pos0] += val;
    anyade[pos1] += val;
    while (pos0 / 2 != pos1 / 2) {
      if (pos0 % 2 == 0) anyade[pos0 + 1] += val;
      pos0 /= 2;
      recalcula(pos0);
      if (pos1 % 2 == 1) anyade[pos1 - 1] += val;
      pos1 /= 2;
      recalcula(pos1);
    }
  }
  while (pos0 > 1) {
    pos0 /= 2;
    recalcula(pos0);
  }
}
long long int sumaentre(int pos0, int pos1) {
  pos0 += primero;
  pos1 += primero;
  if (pos0 > pos1) return 0;
  long long int s = 0;
  long long int c0 = 0, c1 = 0;
  if (pos0 == pos1) {
    s += anyade[pos0];
    c0++;
  } else {
    s += anyade[pos0];
    s += anyade[pos1];
    c0++;
    c1++;
    while (pos0 / 2 != pos1 / 2) {
      if (pos0 % 2 == 0) {
        s += suma[pos0 + 1] + anyade[pos0 + 1] * cuantos[pos0 + 1];
        c0 += cuantos[pos0 + 1];
      }
      pos0 /= 2;
      s += c0 * anyade[pos0];
      if (pos1 % 2 == 1) {
        s += suma[pos1 - 1] + anyade[pos1 - 1] * cuantos[pos1 - 1];
        c1 += cuantos[pos1 - 1];
      }
      pos1 /= 2;
      s += c1 * anyade[pos1];
    }
    c0 += c1;
  }
  while (pos0 > 1) {
    pos0 /= 2;
    s += c0 * anyade[pos0];
  }
  return s;
}
int n;
vector<int> g[limite];
int a[limite];
int posactmin = 1, posactsum = 1;
int posle[limite], posri[limite], posicion[limite];
int profundidad[limite];
int ancestrocomun(int u, int v) {
  return minimoentre(posicion[u], posicion[v]);
}
void recorre(int u, int p, int prof) {
  profundidad[u] = prof;
  posicion[u] = posactmin++;
  posle[u] = posactsum++;
  anyadeentre(posle[u], posle[u], a[u]);
  inserta(posicion[u], pair<int, int>(prof, u));
  vector<int> &ar = g[u];
  for (int i = 0; i < int(ar.size()); i++) {
    int v = ar[i];
    if (v != p) {
      recorre(v, u, prof + 1);
      inserta(posactmin++, pair<int, int>(prof, u));
    }
  }
  posri[u] = posactsum - 1;
}
int main() {
  ios::sync_with_stdio(false);
  for (int i = tope - 1; i >= 1; i--)
    if (i >= primero)
      cuantos[i] = 1;
    else
      cuantos[i] = cuantos[2 * i] + cuantos[2 * i + 1];
  cin >> n;
  int casos;
  cin >> casos;
  for (int i = 1; i <= n; i++) cin >> a[i];
  for (int i = 0; i < n - 1; i++) {
    int u, v;
    cin >> u >> v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  recorre(1, 0, 0);
  int root = 1;
  for (int cas = 0; cas < casos; cas++) {
    int tipo;
    cin >> tipo;
    if (tipo == 1) {
      cin >> root;
    } else if (tipo == 2) {
      int u, v, val;
      cin >> u >> v >> val;
      int uroot = ancestrocomun(u, root);
      int vroot = ancestrocomun(v, root);
      int uv = ancestrocomun(u, v);
      if (uroot == root) {
        if (vroot == root) {
          if (uv == root)
            anyadeentre(1, n, val);
          else
            anyadeentre(posle[uv], posri[uv], val);
        } else {
          anyadeentre(1, n, val);
        }
      } else if (vroot == root) {
        anyadeentre(1, n, val);
      } else if (ancestrocomun(uv, root) == uv) {
        int w = profundidad[uroot] < profundidad[vroot] ? vroot : uroot;
        w = getancestro(posicion[root], profundidad[w] + 1);
        anyadeentre(1, posle[w] - 1, val);
        anyadeentre(posri[w] + 1, n, val);
      } else {
        anyadeentre(posle[uv], posri[uv], val);
      }
    } else if (tipo == 3) {
      int u;
      cin >> u;
      int uroot = ancestrocomun(u, root);
      long long int sol;
      if (u == root) {
        sol = sumaentre(1, n);
      } else if (uroot == root) {
        sol = sumaentre(posle[u], posri[u]);
      } else if (uroot == u) {
        int w = getancestro(posicion[root], profundidad[u] + 1);
        sol = sumaentre(1, posle[w] - 1) + sumaentre(posri[w] + 1, n);
      } else {
        sol = sumaentre(posle[u], posri[u]);
      }
      cout << sol << endl;
    }
  }
}
