#include<bits/stdc++.h>
using namespace std;
long long n,m,k,r,t[200005],f[200005],d[200005],s[200005],top[200005],id[200005],rev[200005],zs[200005],nid,z[200005];
long long ll[401005],rr[401005],he[400105];
long long zl[401005],zr[401005];
long long lazy[401005];
long long a[200005],b[200005],nex[200005],sta[200005];
long long cs,gen,P,xx,yy,aa,bb,cc;
long long daan;
long long buildtree(long long x){
long long oy=0;
s[x]=1;
for(int i=sta[x];i!=0;i=nex[i]){
if(s[b[i]]!=0) continue;
f[b[i]]=x;d[b[i]]=d[x]+1;
long long op=buildtree(b[i]);
s[x]+=op;
if(op>oy){
oy=op;
zs[x]=b[i];
}
}
return s[x];
}
long long potree(long long x,long long g){
rev[x]=++nid;
id[nid]=x;
top[x]=g;
if(zs[x]!=0) potree(zs[x],g);
for(int i=sta[x];i!=0;i=nex[i]){
if(top[b[i]]==0){
potree(b[i],b[i]);
}
}
}
long long xiantree(long long x,long long l,long long r){
long long mid=(l+r)>>1;
ll[x]=l,rr[x]=r;
if(l==r) return he[x]=z[id[l]];
else{
he[x]=(xiantree(x<<1,l,mid)+xiantree((x<<1)+1,mid+1,r))%P;
return he[x];
}
}
long long zha(long long x,long long l,long long r){
long long mid=(ll[x]+rr[x])>>1;
if(lazy[x]!=0){
lazy[x<<1]+=lazy[x];
lazy[(x<<1)+1]+=lazy[x];
he[x]+=lazy[x]*(rr[x]-ll[x]+1);
he[x]%=P;
lazy[x]=0;
}
if(ll[x]==rr[x]) return he[x];
else {
long long ans=0;
if(l<=mid) ans+=zha(x<<1,l,min(mid,r));
if(r>mid) ans+=zha((x<<1)+1,max(mid+1,l),r);
ans%=P;
return ans;
}
}
void gai(long long x,long long l,long long r){
long long mid=(ll[x]+rr[x])>>1;
if(ll[x]==l&&rr[x]==r) {
lazy[x]+=cs;
lazy[x<<1]+=lazy[x];
lazy[(x<<1)+1]+=lazy[x];
he[x]+=lazy[x]*(rr[x]-ll[x]+1);
he[x]%=P;
lazy[x]=0;
return ;
}
if(lazy[x]!=0){
lazy[x<<1]+=lazy[x];
lazy[(x<<1)+1]+=lazy[x];
he[x]+=lazy[x]*(rr[x]-ll[x]+1);
he[x]%=P;
lazy[x]=0;
}
if(ll[x]==rr[x]) return ;
else{
he[x]+=(r-l+1)*cs;
if(l<=mid) gai(x<<1,l,min(mid,r));
if(r>mid) gai((x<<1)+1,max(mid+1,l),r);
}
}
void ling(long long x,long long y){
a[++k]=x,b[k]=y,nex[k]=sta[x],sta[x]=k;
a[++k]=y,b[k]=x,nex[k]=sta[y],sta[y]=k;
}
void caozuo1(long long x,long long y){
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) swap(x,y);
gai(1,rev[x],rev[top[x]]);
x=f[top[x]];
}
if(d[x]<d[y]) swap(x,y);
gai(1,rev[x],rev[y]);
return ;
}
long long caozuo2(long long x,long long y){
long long ans=0;
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) swap(x,y);
ans+=zha(1,rev[x],rev[top[x]]);
ans%=P;
x=f[top[x]];
}
if(d[x]<d[y]) swap(x,y);
ans+=zha(1,rev[x],rev[y]);
ans%=P;
return ans;
}
void caozuo3(long long x){
gai(1,rev[x],rev[x]+s[x]-1);
}
long long caozuo4(long long x){
return (zha(1,rev[x],rev[x]+s[x]-1))%P;
}
int main(){
cin>>n>>m>>gen>>P;
for(int i=1;i<=n;++i) cin>>z[i];
for(int i=1;i<n;++i){
cin>>xx>>yy;
ling(xx,yy);
}
d[gen]=1;
buildtree(gen);
potree(gen,gen);
xiantree(1,1,n);
for(int i=1;i<=m;++i){
cin>>aa;
if(aa==1){
cin>>aa>>bb>>cc;
cs=cc;
caozuo1(aa,bb);
}
else if(aa==2){
cin>>aa>>bb;
cout<<caozuo2(aa,bb)<<endl;
}
else if(aa==3){
cin>>aa>>bb;
cs=bb;
caozuo3(aa);
}
else if(aa==4){
cin>>aa;
cout<<caozuo4(aa)<<endl;
}
}
}