#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#define N 400001
#define aut(u) for(int i=first[u];i;i=nxt[i])
using namespace std;
typedef long long ll;
int first[N],nxt[N],to[N],top,p,n,m,rt;
int dfn[N],dep[N],size[N],fa[N],son[N],val[N],link[N],cnt;
inline int rd(){
int x=0;char c=getchar();
while(c>'9'||c<'0')c=getchar();
while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
return x;
}
inline void add(int x,int y) {
nxt[++top]=first[x];
to[top]=y;
first[x]=top;
return ;
}
namespace segment{
ll sum[N*4],up[N*4];
ll lef(ll x) {return x<<1;}
ll rig(ll x) {return x<<1|1;}
void pushup(ll now) {
sum[now]=sum[lef(now)]+sum[rig(now)];
}
void build(ll now,ll l,ll r){
up[now]=0;
if(l==r){
sum[now]=val[dfn[l]];
return ;
}
ll mid=(l+r)>>1;
build(lef(now),l,mid);
build(rig(now),mid+1,r);
pushup(now);
}
void f(ll now,ll l,ll r,ll k){
up[now]+=k;
sum[now]+=k*(r-l+1);
}
void pushdown(ll now,ll l,ll r){
ll mid=(l+r)>>1;
f(lef(now),l,mid,up[now]);
f(rig(now),mid+1,r,up[now]);
up[now]=0;
}
void update(ll dl,ll dr,ll l,ll r,ll now,ll k){
if(dl<=l&&r<=dr){
sum[now]+=k*(r-l+1);
up[now]+=k;
return ;
}
pushdown(now,l,r);
ll mid=(l+r)>>1;
if(dl<=mid) update(dl,dr,l,mid,lef(now),k);
if(dr>mid) update(dl,dr,mid+1,r,rig(now),k);
pushup(now);
}
ll query(ll dl,ll dr,ll l,ll r,ll now){
ll res=0;
if(dl<=l&&r<=dr) return sum[now];
ll mid=(l+r)>>1;
pushdown(now,l,r);
if(dl<=mid) res+=query(dl,dr,l,mid,lef(now));
if(dr>mid) res+=query(dl,dr,mid+1,r,rig(now));
return res;
}
}
void dfs1(int u,int f){
fa[u]=f;
size[u]=1;
dep[u]=dep[f]+1;
int h=-1;
aut(u){
int v=to[i];
if(v==f) continue;
dfs1(v,u);
size[u]+=size[v];
if(size[v]>h){
h=size[v];
son[u]=v;
}
}
}
void dfs2(int u,int f){
link[u]=f;
dfn[u]=++cnt;
if(!son[u]) return ;
dfs2(son[u],f);
aut(u){
int v=to[i];
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
ll queryPath(int u,int v){
ll res=0;
while(link[u]!=link[v]){
if(dep[link[u]]<dep[link[v]])
swap(u,v);
res=(res+segment::query(dfn[link[u]],dfn[u],1,n,1));
u=fa[link[u]];
}
if(dep[u]>dep[v])
swap(u,v);
res=(res+segment::query(dfn[u],dfn[v],1,n,1));
return res;
}
int main(){
n=rd(); m=rd();
for(int i=1;i<=n;i++) val[i]=rd();
for(int i=1;i<=n-1;i++){
int x=rd(),y=rd();
add(x,y); add(y,x);
}
dfs1(1,0);
dfs2(1,1);
segment::build(1,1,n);
while(m--){
int typ=rd(),x,y;
if(typ==1){
x=rd(); y=rd();
segment::update(dfn[x],dfn[x],1,n,1,y);
}
if(typ==2){
x=rd(); y=rd();
segment::update(dfn[x],dfn[x]+size[x]-1,1,n,1,y);
}
if(typ==3){
x=rd();
printf("%lld\n",queryPath(x,1));
}
}
return 0;
}