#include <bits/stdc++.h>
using namespace std ;
const int N=2e5+5,M=N;
#define int long long
int S,mod;
int n,nxt[M],hd[N],all,go[M];
int dep[N],sz[N],fa[N],son[N];
int dfn[N],id[N],pool,top[N];
#define k1 k<<1
#define k2 k<<1|1
int a[N];
struct Tree{
int s,lazy;
int l,r;
}tr[N<<2];
void help(int k,int v){
tr[k].lazy+=v, tr[k].s+=v*(tr[k].r-tr[k].l+1);
tr[k].lazy%=mod; tr[k].s%=mod;
}
void pushd(int k){
if(tr[k].lazy==0) return;
help(k1,tr[k].lazy),help(k2,tr[k].lazy);
tr[k].lazy=0;
}
int qry(int k,int x,int y){
int t=0;
if(x<=tr[k].l&&y>=tr[k].r)
return tr[k].s%mod;
int md=(tr[k].l+tr[k].r)/2;
pushd(k);
if(x<=md) t+=qry(k1,x,y),t%=mod;
if(y>md) t+=qry(k2,x,y),t%=mod;
return t;
}
void add(int k,int x,int y,int z){
if(x<=tr[k].l&&y>=tr[k].r) return help(k,z);
int md=(tr[k].l+tr[k].r)/2;
pushd(k);
if(x<=md) add(k1,x,y,z);
if(y>md) add(k2,x,y,z);
tr[k].s=tr[k1].s+tr[k2].s,tr[k].s%=mod;
}
void build(int k,int l,int r){
tr[k].l=l,tr[k].r=r;
tr[k].s=0;
if(l==r){
tr[k].s=a[id[l]]; tr[k].s%=mod; return;
}
int md=(l+r)/2;
build(k1,l,md),build(k2,md+1,r);
tr[k].s=tr[k1].s+tr[k2].s,tr[k].s%=mod;
}
void add(int x,int y){
go[++all]=y,nxt[all]=hd[x],hd[x]=all;
}
void dfs1(int x,int par){
fa[x]=par;
sz[x]=1;
dep[x]=dep[par]+1;
son[x]=0;
for(int i=hd[x];i;i=nxt[i]){
int y=go[i]; if(par==y) continue;
dfs1(y,x);
sz[x]+=sz[y];
if(sz[y]>sz[son[x]]) son[x]=y;
}
}
void dfs2(int x,int topf){
dfn[x]=++pool;
id[pool]=x;
top[x]=topf;
if(!son[x]) return ;
dfs2(son[x],topf);
for(int i=hd[x];i;i=nxt[i]){
int y=go[i];
if(y==fa[x]||y==son[x]) continue;
dfs2(y,y);
}
}
int qRange(int x,int y){
int res=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
res+=qry(1,dfn[top[x]],dfn[x]); res%=mod;
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
res+=qry(1,dfn[x],dfn[y]); res%=mod;
return res;
}
void upRange(int x,int y,int z){
z%=mod;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
add(1,dfn[top[x]],dfn[x],z);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
add(1,dfn[x],dfn[y],z);
}
int qSon(int x){
return qry(1,dfn[x],dfn[x]+sz[x]-1)%mod;
}
void upSon(int x,int z){
z%=mod;
add(1,dfn[x],dfn[x]+sz[x]-1,z);
}
signed main(){
int op,i,x,y,z,tes;
cin>>n>>tes>>S>>mod;
for(i=1;i<=n;i++) cin>>a[i];
for(i=1;i<n;i++) cin>>x>>y,add(x,y),add(y,x);
dfs1(S,0); dfs2(S,S);
build(1,1,n);
while(tes--){
cin>>op;
if(op==1){
cin>>x>>y>>z;
upRange(x,y,z);
}
else if(op==2){
cin>>x>>y;
cout<<qRange(x,y)<<endl;
}
else if(op==3){
cin>>x>>y;
upSon(x,y);
}
else if(op==4){
cin>>x;
cout<<qSon(x)<<endl;
}
}
}