#include <bits/stdc++.h>
using namespace std;
long long Read() {
  long long Output = 0, W = 1;
  char Input = getchar();
  while (Input < '0' || Input > '9') {
    if (Input == '-') W = -1;
    Input = getchar();
  }
  while (Input >= '0' && Input <= '9') {
    Output = Output * 10 + Input - '0';
    Input = getchar();
  }
  return Output * W;
}
const long long Inf = 5e17;
int N, M;
struct edge {
  int Next, To;
} Edge[200001];
int Head[100001];
int Lon;
int Capital = 1;
long long Val[100001];
int Fa[100001], Depth[100001];
int Son[100001], Size[100001];
int Id[100001], Now, Idin[100001];
long long Defence[100001];
int Top[100001];
long long Tree[400001];
long long Tag[800001], Last;
void Make(int From, int To) {
  Edge[++Lon].Next = Head[From];
  Edge[Lon].To = To;
  Head[From] = Lon;
}
void DFSa(int Pos, int Deep, int F) {
  Fa[Pos] = F;
  Depth[Pos] = Deep;
  Size[Pos] = 1;
  for (int i = Head[Pos]; i; i = Edge[i].Next) {
    int To = Edge[i].To;
    if (To == F) continue;
    DFSa(To, Deep + 1, Pos);
    Size[Pos] += Size[To];
    if (Size[Son[Pos]] < Size[To]) Son[Pos] = To;
  }
}
void DFSb(int Pos, int Linetop) {
  Top[Pos] = Linetop;
  Id[Pos] = ++Now;
  Idin[Now] = Pos;
  Val[Now] = Defence[Pos];
  if (!Son[Pos]) return;
  DFSb(Son[Pos], Linetop);
  for (int i = Head[Pos]; i; i = Edge[i].Next) {
    int To = Edge[i].To;
    if (To == Son[Pos] || To == Fa[Pos]) continue;
    DFSb(To, To);
  }
}
void Pushup(int Pos) { Tree[Pos] = Tree[(Pos << 1)] + Tree[((Pos << 1) | 1)]; }
void Build(int L, int R, int Pos) {
  if (L == R) {
    Tree[Pos] = Val[L];
    return;
  }
  Build(L, ((L + R) >> 1), (Pos << 1));
  Build(((L + R) >> 1) + 1, R, ((Pos << 1) | 1));
  Pushup(Pos);
}
void Down(int L, int R, int Pos) {
  Tree[Pos] += Tag[Pos] * (R - L + 1);
  Tag[(Pos << 1)] += Tag[Pos];
  Tag[((Pos << 1) | 1)] += Tag[Pos];
  Tag[Pos] = 0;
}
void Pushdown(int L, int R, int Pos) {
  if (Tag[(Pos << 1)]) Down(L, ((L + R) >> 1), (Pos << 1));
  if (Tag[((Pos << 1) | 1)]) Down(((L + R) >> 1) + 1, R, ((Pos << 1) | 1));
}
void Update(int L, int R, int Pos, int UL, int UR, long long V) {
  if (L >= UL && R <= UR) {
    Tree[Pos] += V * (R - L + 1);
    Tag[(Pos << 1)] += V;
    Tag[((Pos << 1) | 1)] += V;
    return;
  }
  Pushdown(L, R, Pos);
  if (((L + R) >> 1) >= UL) Update(L, ((L + R) >> 1), (Pos << 1), UL, UR, V);
  if (((L + R) >> 1) < UR)
    Update(((L + R) >> 1) + 1, R, ((Pos << 1) | 1), UL, UR, V);
  Pushup(Pos);
}
int LCA(int X, int Y) {
  while (Top[X] != Top[Y]) {
    if (Depth[Top[X]] < Depth[Top[Y]]) swap(X, Y);
    Last = Id[Top[X]];
    X = Fa[Top[X]];
  }
  if (Depth[X] > Depth[Y]) swap(X, Y);
  if (X != Y) Last = Id[X] + 1;
  return X;
}
long long Query(int L, int R, int Pos, int QL, int QR) {
  if (L >= QL && R <= QR) return Tree[Pos];
  Pushdown(L, R, Pos);
  long long Res = 0;
  if (((L + R) >> 1) >= QL) Res = Query(L, ((L + R) >> 1), (Pos << 1), QL, QR);
  if (((L + R) >> 1) < QR)
    Res += Query(((L + R) >> 1) + 1, R, ((Pos << 1) | 1), QL, QR);
  return Res;
}
int main() {
  N = Read(), M = Read();
  for (int i = 1; i <= N; ++i) Defence[i] = Read();
  for (int i = 1; i < N; ++i) {
    int X = Read(), Y = Read();
    Make(X, Y);
    Make(Y, X);
  }
  DFSa(1, 1, 0);
  DFSb(1, 1);
  Build(1, N, 1);
  for (int i = 1; i <= M; ++i) {
    int Op = Read(), X = Read();
    if (Op == 1)
      Capital = X;
    else if (Op == 2) {
      int Y = Read();
      long long V = Read();
      int Fir = LCA(X, Y);
      int Sec = LCA(X, Capital);
      int Thi = LCA(Y, Capital);
      int Posi = Fir ^ Sec ^ Thi;
      if (Capital == 1 || LCA(Posi, Capital) != Posi)
        Update(1, N, 1, Id[Posi], Id[Posi] + Size[Posi] - 1, V);
      else if (Capital == Posi)
        Update(1, N, 1, 1, N, V);
      else {
        if (Last + Size[Idin[Last]] <= N)
          Update(1, N, 1, Last + Size[Idin[Last]], N, V);
        if (Last > 1) Update(1, N, 1, 1, Last - 1, V);
      }
    } else {
      if (Capital == 1 || LCA(X, Capital) != X)
        printf("%lld\n", Query(1, N, 1, Id[X], Id[X] + Size[X] - 1));
      else if (Capital == X)
        printf("%lld\n", Tree[1]);
      else {
        long long Fir = 0;
        if (Last + Size[Idin[Last]] <= N)
          Fir = Query(1, N, 1, Last + Size[Idin[Last]], N);
        if (Last > 1) Fir += Query(1, N, 1, 1, Last - 1);
        printf("%lld\n", Fir);
      }
    }
  }
  return 0;
}
