#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define int long long
const int N = 1e6+5;
int n,m,r,cnt;
int fa[N],dep[N],siz[N],son[N],top[N],val[N],in[N],rnk[N],out[N],head[N];
struct Edge{
int to,next;
}edge[N<<1];
struct Tree{
int t[N];
inline int lowbit(int x){return x&(-x);}
inline void modify(int x,int k){while(x<=N) t[x]+=k,x+=lowbit(x);}
inline int query(int x){int res=0;while(x) res+=t[x],x-=lowbit(x);return res;}
inline void add(int l,int r,int val){modify(l,val);modify(r+1,-val);}
}t1,t2;
inline void add(int u,int v){
edge[++cnt]={v,head[u]};
head[u]=cnt;
}
inline int read(){
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^'0');c=getchar();}
return x*f;
}
inline void dfs1(int u){
siz[u]=1;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==fa[u]) continue;
fa[v]=u,dep[v]=dep[u]+1;
dfs1(v);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
inline void dfs2(int u){
in[u]=++cnt;
rnk[cnt]=u;
if(son[u]){
top[son[u]]=top[u],val[son[u]]+=val[u];
dfs2(son[u]);
}
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==fa[u]||v==son[u]) continue;
top[v]=v;
val[v]+=val[u];
dfs2(v);
}
out[u]=cnt;
}
inline int LCA(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]>dep[top[v]]) swap(u,v);
v=fa[top[v]];
}
return dep[u]>dep[v]?v:u;
}
inline int query(int x){
if(x==0) return 0;
return val[x]+t1.query(in[x])+t2.query(in[x])*(dep[x]+1);
}
signed main(){
n=read(),m=read(),r=read();
for(int i=1;i<=n;i++) val[i]=read();
for(int i=1,u,v;i<n;i++){
u=read(),v=read();
add(u,v);add(v,u);
}
dep[r]=1,top[r]=r;
dfs1(r);
dfs2(r);
for(int i=1,op,a,b;i<=m;i++){
op=read(),a=read(),b=read();
if(op==1) t1.add(in[a],out[a],b);
else if(op==2) t1.add(in[a],out[a],b),t2.add(in[a],out[a],-1ll*b*dep[a]);
else if(op==3){
int Lca=LCA(a,b);
printf("%lld\n",query(a)+query(b)-query(Lca)-query(fa[Lca]));
}
}
return 0;
}