#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+10;
inline int read(){
int f=1,x=0;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
int n,m,p,rt,a[N];
int u,v,w;
int head[N],nxt[N<<1],to[N<<1],cnt=0;
void add(int u,int v)
{
nxt[++cnt]=head[u];
to[cnt]=v;
head[u]=cnt;
}
int num[N],renum[N],siz[N],son[N],tp[N],fa[N],dep[N];
void dfs1(int x,int f)
{
siz[x]=1;
fa[x]=f;
dep[x]=dep[f]+1;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==f) continue;
dfs1(y,x);
siz[x]+=siz[y];
if(siz[y]>siz[son[x]]) son[x]=y;
}
}
void dfs2(int x,int p)
{
tp[x]=p;
num[x]=++cnt;
renum[cnt]=x;
if(!son[x]) return;
dfs2(son[x],p);
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==fa[x]||y==son[x]) continue;
dfs2(y,y);
}
}
int sum[N<<2],lat[N<<2];
void pushup(int rt)
{
sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%p;
}
void pushdown(int l,int r,int rt)
{
if(!lat[rt]) return;
int mid=(l+r)>>1;
sum[rt<<1]=(sum[rt<<1]+lat[rt]*(mid-l+1))%p*1LL;
sum[rt<<1|1]=(sum[rt<<1|1]+lat[rt]*(r-mid))%p*1LL;
lat[rt<<1]=(lat[rt<<1]+lat[rt])%p;
lat[rt<<1|1]=(lat[rt<<1|1]+lat[rt])%p;
lat[rt]=0;
}
void buildup(int rt,int l,int r)
{
if(l==r)
{
sum[rt]=a[renum[l]]%p;
return;
}
int mid=(l+r)>>1;
buildup(rt<<1,l,mid);
buildup(rt<<1|1,mid+1,r);
pushup(rt);
}
int query(int rt,int L,int R,int l,int r)
{
if(L==l&&r==R)
{
return sum[rt];
}
pushdown(L,R,rt);
int mid=(L+R)>>1;
if(mid>=r) return query(rt<<1,L,mid,l,r);
else if(mid<l) return query(rt<<1|1,mid+1,R,l,r);
else return ((query(rt<<1,L,mid,l,mid)+query(rt<<1|1,mid+1,R,mid+1,r))%p+p)%p;
}
void update(int rt,int L,int R,int l,int r,int x)
{
if(L==l&&r==R)
{
sum[rt]=((sum[rt]+x*(l-r+1))%p+p)%p;
lat[rt]=((lat[rt]+x)%p+p)%p;
return;
}
pushdown(L,R,rt);
int mid=(L+R)>>1;
if(mid>=r) update(rt<<1,L,mid,l,r,x);
else if(mid<l) update(rt<<1|1,mid+1,R,l,r,x);
else update(rt<<1,L,mid,l,mid,x),update(rt<<1|1,mid+1,R,mid+1,r,x);
pushup(rt);
}
int od;
void lcanc(int x,int y,int f,int w)
{
int res=0;
while(tp[x]!=tp[y])
{
if(dep[tp[x]]>dep[tp[y]]) swap(x,y);
if(f) update(1,1,n,num[tp[y]],num[y],w);
else res=(res+query(1,1,n,num[tp[y]],num[y]))%p;
y=fa[tp[y]];
}
if(dep[y]>dep[x]) swap(x,y);
if(f) update(1,1,n,num[y],num[x],w);
else
{
res=(res+query(1,1,n,num[y],num[x]))%p;
printf("%lld\n",res);
}
}
signed main(){
n=read();
m=read();
rt=read();
p=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<n;i++)
{
u=read();
v=read();
add(u,v);
add(v,u);
}
cnt=0;
dfs1(rt,0);
dfs2(rt,rt);
buildup(1,1,n);
for(int i=1;i<=m;i++)
{
od=read();
if(od==1)
{
u=read();
v=read();
w=read();
w%=p;
lcanc(u,v,1,w);
}else if(od==2)
{
u=read();
v=read();
lcanc(u,v,0,0);
}else if(od==3)
{
u=read();
w=read();
w%=p;
update(1,1,n,num[u],num[u]+siz[u]-1,w);
}else
{
u=read();
printf("%lld\n",query(1,1,n,num[u],num[u]+siz[u]-1));
}
}
return 0;
}