#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<ctime>
#include<queue>
using namespace std;
const int N=100009;
int n,m,s,mod,w[N],head[N],tot,wt[N];
int f[N],d[N],son[N],top[N],sz[N],id[N],cnt;
int tag[N<<2],sum[N<<2];
struct node{int to,nxt;}a[N<<2];
int mn(int i,int j){return i<j?i:j;}
int mx(int i,int j){return i<j?j:i;}
int jdz(int k){return k>0?k:-k;}
inline int read()
{
register int x=0,f=1;
char c=getchar();
while(c<'0' || c>'9') {if(c=='-')f=-1;c = getchar();}
while(c>='0' && c<='9') { x = x*10 + c -48; c = getchar(); }
return x*f;
}
void add(int x,int y)
{
a[++tot].nxt=head[x];head[x]=tot;
a[tot].to=y;
}
void dfs1(int s,int fa)
{
d[s]=d[fa]+1;f[s]=fa;sz[s]=1;
for(int i=head[s];i;i=a[i].nxt)
{
int v=a[i].to;
if(v==fa) continue;
dfs1(v,s);
sz[s]+=sz[v];
if(!son[s]||sz[son[s]]<sz[v]) son[s]=v;
}
}
void dfs2(int s,int gen)
{
top[s]=gen;wt[++cnt]=w[s];id[s]=cnt;
if(!son[s]) return ;
dfs2(son[s],gen);
for(int i=head[s];i;i=a[i].nxt)
{
int v=a[i].to;
if(v==f[s]||v==son[s]) continue;
else dfs2(v,v);
}
}
void pushup(int t){sum[t]=(sum[t*2]+sum[t*2+1])%mod;}
void pushdown(int t,int l,int r)
{
if(!tag[t]) return ;
int mid=(l+r)>>1;
sum[t*2]+=tag[t]*(mid-l+1);sum[t*2+1]+=tag[t]*(r-mid);
tag[t*2]+=tag[t];tag[t*2+1]+=tag[t];
tag[t]=0;
}
void build(int t,int tl,int tr)
{
if(tl==tr) {sum[t]=wt[tl];return;}
int mid=(tl+tr)>>1;
build(t*2,tl,mid);build(t*2+1,mid+1,tr);
pushup(t);
}
int query(int t,int tl,int tr,int l,int r)
{
if(l<=tl&&tr<=r) return sum[t]%mod;
pushdown(t,tl,tr);
int mid=(tl+tr)>>1,anss=0;
if(l<=mid) anss+=query(t*2,tl,mid,l,r);
if(r>mid) anss+=query(t*2+1,mid+1,tr,l,r);
return anss%mod;
}
void update(int t,int tl,int tr,int l,int r,int k)
{
if(l<=tl&&tr<=r) {sum[t]+=(tr-tl+1)*k;tag[t]+=k;return ;}
pushdown(t,tl,tr);
int mid=(tl+tr)>>1;
if(l<=mid) update(t*2,tl,mid,l,r,k);
if(r>mid) update(t*2+1,mid+1,tr,l,r,k);
pushup(t);
}
signed main()
{
n=read();m=read();s=read();mod=read();
for(int i=1;i<=n;i++) w[i]=read();
for(int x,y,i=1;i<n;i++)
{
x=read();y=read();
add(x,y);add(y,x);
}
dfs1(s,0);
dfs2(s,s);
for(int opt,x,y,z,i=1;i<=m;i++)
{
opt=read();
if(opt==1)
{
x=read();y=read();z=read();z%=mod;
while(top[x]!=top[y])
{
if(d[top[x]]>d[top[y]]) {update(1,1,n,id[top[x]],id[x],z);x=f[top[x]];}
else {update(1,1,n,id[top[y]],id[y],z);y=f[top[y]];}
}
if(d[x]>d[y]) swap(x,y);
update(1,1,n,id[x],id[y],z);continue;
}
if(opt==2)
{
x=read();y=read();int ans=0;
while(top[x]!=top[y])
{
if(d[top[x]]>d[top[y]]) {ans+=query(1,1,n,id[top[x]],id[x]);x=f[top[x]];}
else {ans=(ans+query(1,1,n,id[top[y]],id[y]))%mod;y=f[top[y]];}
}
if(d[x]>d[y]) swap(x,y);
ans+=query(1,1,n,id[x],id[y]);ans%=mod;
printf("%d\n",ans);continue;
}
if(opt==3) {x=read();z=read();update(1,1,n,id[x],id[x]+sz[x]-1,z); }
if(opt==4) {x=read();printf("%d\n",query(1,1,n,id[x],id[x]+sz[x]-1)); }
}
return 0;
}