#include<iostream>
#include<vector>
#include<bitset>
#define int long long
using namespace std;
int n,m,srt,p,dt[100000],s,t,st[100000],sn[100000],stp[100000],sq[100000],ps[100000],sl[400000],sr[400000],v[400000],lzy[400000],k,sg,x,y,z,dep[100000],ans,fa[100000];
vector<int> tr[100000];
bool vis[100000];
void dfs1(int rt){
vis[rt]=true;
st[rt]=1;
sn[rt]=-1;
for(int i=0;i<tr[rt].size();i++){
if(!vis[tr[rt][i]]){
dep[tr[rt][i]]=dep[rt]+1;
fa[tr[rt][i]]=rt;
dfs1(tr[rt][i]);
st[rt]+=st[tr[rt][i]];
if(st[sn[rt]]<st[tr[rt][i]]){
sn[rt]=tr[rt][i];
}
}
}
return;
}
void dfs2(int tp,int rt){
vis[rt]=false;
stp[rt]=tp;
sq[k]=rt;
ps[rt]=k;
k++;
if(sn[rt]!=-1){
dfs2(tp,sn[rt]);
}
for(int i=0;i<tr[rt].size();i++){
if(vis[tr[rt][i]]){
dfs2(tr[rt][i],tr[rt][i]);
}
}
return;
}
void psd(int ix){
lzy[ix<<1]+=lzy[ix]%p;
lzy[ix<<1]%=p;
v[ix<<1]+=lzy[ix]*(sr[ix<<1]-sl[ix<<1]+1)%p;
v[ix<<1]%=p;
lzy[(ix<<1)^1]+=lzy[ix]%p;
lzy[(ix<<1)^1]%=p;
v[(ix<<1)^1]+=lzy[ix]*(sr[(ix<<1)^1]-sl[(ix<<1)^1]+1)%p;
v[ix]%=p;
lzy[ix]=0;
return;
}
void crt(int ix,int l,int r){
sl[ix]=l;
sr[ix]=r;
if(l!=r){
crt(ix<<1,l,(l+r)>>1);
crt((ix<<1)^1,((l+r)>>1)+1,r);
v[ix]=(v[ix<<1]+v[(ix<<1)^1])%p;
}
else{
v[ix]=dt[sq[l]]%p;
}
return;
}
void upd(int ix,int l,int r,int c){
psd(ix);
if(sl[ix]!=l||sr[ix]!=r){
if(r<=(sl[ix]+sr[ix])>>1){
upd(ix<<1,l,r,c);
}
else if(l>(sl[ix]+sr[ix])>>1){
upd((ix<<1)^1,l,r,c);
}
else{
upd(ix<<1,l,(sl[ix]+sr[ix])>>1,c);
upd((ix<<1)^1,((sl[ix]+sr[ix])>>1)+1,r,c);
}
v[ix]=(v[ix<<1]+v[(ix<<1)^1])%p;
}
else{
lzy[ix]+=c;
lzy[ix]%=p;
v[ix]+=c*(sr[ix]-sl[ix]+1)%p;
v[ix]%=p;
}
return;
}
int qry(int ix,int l,int r){
psd(ix);
if(sl[ix]!=l||sr[ix]!=r){
if(r<=(sl[ix]+sr[ix])>>1){
return qry(ix<<1,l,r)%p;
}
else if(l>(sl[ix]+sr[ix])>>1){
return qry((ix<<1)^1,l,r)%p;
}
else{
return qry(ix<<1,l,(sl[ix]+sr[ix])>>1)%p+qry((ix<<1)^1,((sl[ix]+sr[ix])>>1)+1,r)%p;
}
}
else{
return v[ix]%p;
}
}
signed main(){
//freopen("P3384_8.in","r",stdin);
scanf("%lld%lld%lld%lld",&n,&m,&srt,&p);
for(int i=0;i<n;i++){
scanf("%lld",&dt[i]);
dt[i]%=p;
}
for(int i=0;i<n-1;i++){
scanf("%lld%lld",&s,&t);
tr[s-1].push_back(t-1);
tr[t-1].push_back(s-1);
}
dfs1(srt-1);
dfs2(srt-1,srt-1);
crt(1,0,n-1);
for(int i=0;i<m;i++){
scanf("%lld",&sg);
switch(sg){
case 1:
scanf("%lld%lld%lld",&x,&y,&z);
z%=p;
x--;
y--;
while(stp[x]!=stp[y]){
if(dep[stp[x]]<dep[stp[y]]){
swap(x,y);
}
upd(1,ps[stp[x]],ps[x],z);
x=fa[stp[x]];
}
if(dep[x]<dep[y]){
upd(1,ps[x],ps[y],z);
}
else{
upd(1,ps[y],ps[x],z);
}
break;
case 2:
scanf("%lld%lld",&x,&y);
x--;
y--;
ans=0;
while(stp[x]!=stp[y]){
if(dep[stp[x]]<dep[stp[y]]){
swap(x,y);
}
ans+=qry(1,ps[stp[x]],ps[x])%p;
x=fa[stp[x]];
}
if(dep[x]<dep[y]){
ans+=qry(1,ps[x],ps[y])%p;
}
else{
ans+=qry(1,ps[y],ps[x])%p;
}
printf("%lld\n",ans%p);
break;
case 3:
scanf("%lld%lld",&x,&z);
z%=p;
upd(1,ps[x-1],ps[x-1]+st[x-1]-1,z);
break;
case 4:
scanf("%lld",&x);
printf("%lld\n",qry(1,ps[x-1],ps[x-1]+st[x-1]-1)%p);
break;
default:
break;
}
}
return 0;
}