#include<bits/stdc++.h>
using namespace std;
#define For(i, l, r) for(int i=(l);i<=(r);++i)
#define Rfor(i, r, l) for(int i=(r);i>=(l);--i)
#define O(x) cerr<<#x<<":"<<x<<endl
#define O_(x,y)cerr<<#x<<":"<<x<<" "<<#y<<":"<<y<<endl
#define LO(a, l, r) For(supervariable, l, r)cerr<<a[supervariable]<<" ";putchar('\n')
#define FS(v,V,u,fa) for(int v:V[(u)])if(v!=(fa))
#define FENGE cout<<"----------------------------------------------------------"<<endl;
int read(){int x=0,t=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')t=-t;ch=getchar();}while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();return x*t;}
const int N=100005;
const long long yao=1;
int a[N];
vector<int> V[N];
int siz[N],son[N],dep[N],n,fa[N];
int top[N],dfn[N],seq[N],out[N];
void dfs1(int x,int fat)
{
dep[x]=dep[fat]+1;siz[x]=1;fa[x]=fat;
FS(v,V,x,fat){dfs1(v,x),siz[x]+=siz[v];if(siz[v]>siz[son[x]])son[x]=v;}
}
namespace SEG
{
long long tr[N<<3],lazy[N<<3];
void pushUp(int x){tr[x]=tr[x<<1]+tr[x<<1|1];}
void pushDown(int x,int l,int r)
{
int mid=l+r>>1;
tr[x<<1]+=lazy[x]*(mid-l+1);tr[x<<1|1]+=lazy[x]*(r-mid);
lazy[x<<1]+=lazy[x];lazy[x<<1|1]+=lazy[x];
lazy[x]=0;
}
void update(int x,int l,int r,int L,int R,int val)
{
if(L<=l&&R>=r){tr[x]+=yao*val*(r-l+1);lazy[x]+=val;return;}
int mid=l+r>>1;pushDown(x,l,r);
if(L<=mid)update(x<<1,l,mid,L,R,val);
if(R>mid)update(x<<1|1,mid+1,r,L,R,val);
pushUp(x);
}
long long query(int x,int l,int r,int L,int R)
{
if(L<=l&&R>=r)return tr[x];
int mid=l+r>>1;pushDown(x,l,r);
long long res=0;
if(L<=mid)res+=query(x<<1,l,mid,L,R);
if(R>mid)res+=query(x<<1|1,mid+1,r,L,R);
return res;
}
}
void dfs2(int x,bool isnew)
{
dfn[x]=++dfn[0];seq[dfn[0]]=x;
if(isnew)top[x]=x;else top[x]=top[fa[x]]; SEG::update(1, 1, n, dfn[x], dfn[x], a[x]);
if(V[x].size()==1&&fa[x])goto End;
dfs2(son[x],0);
FS(v,V,x,fa[x])if(v!=son[x])dfs2(v,1);
End:;
out[x]=dfn[0];
}
int getLca(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
return y;
}
void update(int x,int val){SEG::update(1, 1, n, dfn[x], out[x], val);}
long long query(int x){return SEG::query(1, 1, n, dfn[x], out[x]);}
int rt=1;
bool inSub(int x,int y){return dfn[x]<=dfn[y]&&out[x]>=out[y];}
int main()
{
n=read();int q=read();
For(i, 1, n)a[i]=read();
For(i, 1, n-1){int x=read(),y=read();V[x].emplace_back(y);V[y].emplace_back(x);}
dfs1(1,0);dfs2(1,1);
For(i, 1, q)
{
int op=read();
if(op==1){rt=read();continue;}
if(op==2)
{
int u=read(),v=read(),x=read();
int Luv=getLca(u,v),Lur=getLca(u,rt),Lvr=getLca(v,rt);
if(Lur==Lvr)
{
update(Luv,x);
continue;
}
if(Lur==Luv)swap(Lur,Lvr),swap(u,v);
update(1,x);
FS(v,V,Lur,fa[Lur])
if(inSub(v,rt))update(v,-x);
}
if(op==3)
{
int u=read();
if(!inSub(u,rt)||u==rt){printf("%lld\n",query(u));continue;}
FS(v,V,u,fa[u])
if(inSub(v,rt))printf("%lld\n",query(1)-query(v));
}
}
}