#include<bits/stdc++.h>
using namespace std;
int N,M,R,P;
int dw[100010];
vector<int> e[100010];
int fa[100010],dth[100010],hs[100010],siz[100010];
int dfn[100010],rsk[100010],top[100010];
long long tree[400010],tag[400010];
void dfs1(int x){
int maxx=0;
siz[x]++;dth[x]=dth[fa[x]]+1;
for(int i=0;i<e[x].size();i++){
int v=e[x][i];
if(v==fa[x]) continue;
fa[v]=x;dfs1(v);siz[x]+=siz[v];
if(siz[v]>maxx){maxx=siz[v];hs[x]=v;}
}
}
void dfs2(int x,int r){
top[x]=r;dfn[x]=++dfn[0];rsk[dfn[0]]=x;
if( hs[x] ) dfs2(hs[x],r);
else return ;
for(int i=0;i<e[x].size();i++){
int v=e[x][i];
if(dfn[v]) continue;
dfs2(v,v);
}
}
void build(int x,int l,int r){
if(l==r){ tree[x]= dw[rsk[r]];return ;}
int mid=(l+r)>>1;
build((x<<1),l,mid);build((x<<1)+1,mid+1,r);
tree[x]=tree[x<<1]+tree[(x<<1)+1];tree[x]%=P;
}
void update(int x,int l,int r,const int L,const int R,int k){
if(L<=l && r<=R ){ tree[x]+=(r-l+1)*k%P;tree[x]%=P;tag[x]+=k;tag[x]%=P; return ;}
int mid=(l+r)>>1;
if(mid>=L) update(x<<1,l,mid,L,R,k);
if(mid<R) update((x<<1)+1,mid+1,r,L,R,k);
tree[x]=tree[x<<1]+tree[(x<<1)+1];tree[x]%=P;
}
void pushdown (int x,int l,int r){ //pushdown 下传懒标记
int ls=x<<1,rs=(x<<1)+1;
int mid=(l+r)>>1,llen=mid-l+1,rlen=r-mid;
tree[ls]+=tag[x]*llen%P;tree[ls]%=P;
tree[rs]+=tag[x]*rlen%P;tree[rs]%=P;
tag[ls]+=tag[x];tag[rs]+=tag[x];
tag[ls]%=P;tag[rs]%=P;tag[x]=0;
}
int query(int x,int l,int r,int L,int R){
if(L<=l && r<=R ) return tree[x];
int res=0;
if(tag[x]) pushdown(x,l,r);
int mid=(l+r)>>1;
if( L<=mid ) res+=query(x<<1,l,mid,L,R),res%=P;
if( mid<R ) res+=query((x<<1)+1,mid+1,r,L,R),res%=P;
return res;
}
void op1(int x,int y,int z){
while(top[x]!=top[y]){
if(dth[top[x]]>dth[top[y]]){
update(1,1,N,dfn[top[x]],dfn[x],z);
x=fa[top[x]];
}
else{
update(1,1,N,dfn[top[y]],dfn[y],z);
y=fa[top[y]];
}
}
if(dfn[x]<dfn[y]) update(1,1,N,dfn[x],dfn[y],z);
else update(1,1,N,dfn[y],dfn[x],z);
}
int op2(int x,int y){
int res=0;
while(top[x]!=top[y]){
if(dth[top[x]]>dth[top[y]]){
res+=query(1,1,N,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
else{
res+=query(1,1,N,dfn[top[y]],dfn[y]);
y=fa[top[y]];
}
res%=P;
}
if(dfn[x]<dfn[y]) res+=query(1,1,N,dfn[x],dfn[y]);
else res+=query(1,1,N,dfn[y],dfn[x]);
return res%P;
}
int main(){
cin>>N>>M>>R>>P;
for(int i=1;i<=N;i++) cin>>dw[i];
int u,v;
for(int i=1;i<N;i++) cin>>u>>v,e[u].push_back(v),e[v].push_back(u);
dfs1(R);dfs2(R,R);build(1,1,N);
while(M--){
int op,x,y,z;cin>>op;
if(op==1) {cin>>x>>y>>z;op1(x,y,z%P);}
if(op==2) {cin>>x>>y; cout<<op2(x,y)<<endl;}
if(op==3) {cin>>x>>z;update(1,1,N,dfn[x],dfn[x]+siz[x]-1,z%P); }
if(op==4) {cin>>x; cout<<query(1,1,N,dfn[x],dfn[x]+siz[x]-1)<<endl;}
}
return 0;
}