码风丑陋不喜勿喷
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int kM=1e5+5;
ll sl,sr,d,t[kM],i,n,o,x,y,z,p,q,root,cnt,num,f[kM],id[kM],top[kM],sz[kM],dis[kM],ne[kM<<1],to[kM<<1],ed[kM];
struct T{
ll sum,laz;
}tr[kM<<3];
bool h[kM];
void add(){
ne[++cnt]=ed[x],to[cnt]=y,ed[x]=cnt;
swap(x,y);
if(cnt&1)add();
return;
}
void dfs1(ll rt,ll fa){
ll i,ans=0;
f[rt]=fa,sz[rt]=1,dis[rt]=dis[fa]+1;
for(i=ed[rt];i;i=ne[i]){
if(fa!=to[i]){
dfs1(to[i],rt);
sz[rt]+=sz[to[i]];
if(sz[to[i]]>sz[ans])ans=to[i];
}
}
h[ans]=1;
return;
}
void dfs2(ll rt,ll fa){
ll i;
id[rt]=++num;
if(!h[rt])top[rt]=rt;
else top[rt]=top[fa];
for(i=ed[rt];i;i=ne[i]){
if(fa!=to[i]&&h[to[i]]){
dfs2(to[i],rt);
}
}
for(i=ed[rt];i;i=ne[i]){
if(fa!=to[i]&&!h[to[i]]){
dfs2(to[i],rt);
}
}
return;
}
void laz_tag(ll rt,ll l,ll r,ll mid){
tr[rt<<1].laz+=tr[rt].laz;
tr[rt<<1].sum+=(tr[rt].laz*(mid-l+1))%p;
tr[rt<<1|1].laz+=tr[rt].laz;
tr[rt<<1|1].sum+=(tr[rt].laz*(r-mid))%p;
tr[rt].laz=0;
tr[rt<<1].sum%=p,tr[rt<<1].laz%=p;
tr[rt<<1|1].sum%=p,tr[rt<<1|1].laz%=p;
return;
}
void update(ll rt,ll l,ll r){
ll mid=(l+r)>>1;
laz_tag(rt,l,r,mid);
if(sl<=l&&r<=sr){
tr[rt].laz+=d;
tr[rt].sum+=(d*(r-l+1))%p;
tr[rt].sum%=p;
tr[rt].laz%=p;
return;
}
if(sl<=mid)update(rt<<1,l,mid);
if(mid<sr)update(rt<<1|1,mid+1,r);
tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
tr[rt].sum%=p;
return;
}
ll push_down(ll rt,ll l,ll r){
ll mid=(l+r)>>1,ret=0;
laz_tag(rt,l,r,mid);
if(sl<=l&&r<=sr){
return tr[rt].sum%p;
}
if(sl<=mid)ret+=push_down(rt<<1,l,mid);
ret%=p;
if(mid<sr)ret+=push_down(rt<<1|1,mid+1,r);
tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
tr[rt].sum%=p;
ret%=p;
return ret;
}
void lca_u(ll x,ll y){
while(top[x]!=top[y]){
if(dis[top[x]]<dis[top[y]])swap(x,y);
sl=id[top[x]],sr=id[x];
update(1,1,n);
x=f[top[x]];
}
if(dis[x]<dis[y])swap(x,y);
sl=id[x],sr=id[y];
update(1,1,n);
return;
}
ll lca_p(ll x,ll y){
ll ans=0;
while(top[x]!=top[y]){
if(dis[top[x]]<dis[top[y]])swap(x,y);
sl=id[top[x]],sr=id[x];
ans+=push_down(1,1,n);
ans%=p;
x=f[top[x]];
}
if(dis[x]<dis[y])swap(x,y);
sl=id[x],sr=id[y];
ans+=push_down(1,1,n);
ans%=p;
return ans;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>q>>root>>p;
for(i=1;i<=n;i++){
cin>>t[i];
t[i]%=p;
}
for(i=1;i<n;i++){
cin>>x>>y;
add();
}
dfs1(root,0);
dfs2(root,root);
for(i=1;i<=n;i++){
d=t[i],sl=id[i],sr=id[i];
update(1,1,n);
}
while(q--){
cin>>o;
if(o==1){
cin>>x>>y>>d;
d%=p;
lca_u(x,y);
}
if(o==2){
cin>>x>>y;
cout<<(lca_p(x,y)%p+p)%p<<"\n";
}
if(o==3){
cin>>x>>d;
d%=p;
sl=id[x],sr=id[x]+sz[x]-1;
update(1,1,n);
}
if(o==4){
cin>>x;
sl=id[x],sr=id[x]+sz[x]-1;
cout<<(push_down(1,1,n)%p+p)%p<<"\n";
}
}
return 0;
}