#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=100010;
int head[N],ver[2*N],nxt[2*N],tot;
struct node{
int l,r,ls,rs,sum,lazy;
}a[2*N];
int n,m,r,rt,mod,v[N],cnt,f[N],d[N],son[N],siz[N],top[N],idx[N],rk[N];
void add(int x,int y){
ver[++tot]=y;nxt[tot]=head[x];head[x]=tot;
}
void dfs1(int x){
siz[x]=1;d[x]=d[f[x]]+1;
for(int i=head[x];i;i=nxt[i]){
int v=ver[i];
if(v!=f[x]){
f[v]=x;
dfs1(v);
siz[x]+=siz[v];
if(siz[son[x]]<siz[v])son[x]=v;
}
}
}
void dfs2(int x,int tp){
top[x]=tp;idx[x]=++cnt;rk[cnt]=x;
if(son[x])dfs2(son[x],tp);
for(int i=head[x];i;i=nxt[i]){
int v=ver[i];
if(v!=f[x]&&v!=son[x])dfs2(v,v);
}
}
inline void pushup(int x){
a[x].sum=(a[a[x].ls].sum+a[a[x].rs].sum)%mod;
}
void build(int l,int r,int x){
if(l==r){
a[x].sum=v[rk[l]]%mod,a[x].l=a[x].r=l;
return;
}
int mid=(l+r)>>1;
a[x].ls=cnt++,a[x].rs=cnt++;
build(l,mid,a[x].ls);build(mid+1,r,a[x].rs);
a[x].l=a[a[x].ls].l,a[x].r=a[a[x].rs].r;
pushup(x);
}
inline int len(int x){
return a[x].r-a[x].l+1;
}
inline void pushdown(int x){
if(a[x].lazy){
int ls=a[x].ls,rs=a[x].rs,lz=a[x].lazy;
a[ls].lazy=(a[ls].lazy+lz)%mod;
a[rs].lazy=(a[rs].lazy+lz)%mod;
a[ls].sum=(a[ls].sum+lz*len(ls)%mod);
a[rs].sum=(a[rs].sum+lz*len(rs)%mod);
a[x].lazy=0;
}
}
void update(int l,int r,int c,int x){
if(a[x].l>=l&&a[x].r<=r){
a[x].lazy=(a[x].lazy+c)%mod;
a[x].sum=(a[x].sum+len(x)*c)%mod;
return;
}
pushdown(x);
int mid=(a[x].l+a[x].r)>>1;
if(mid>=l)update(l,r,c,a[x].ls);
if(mid<r)update(l,r,c,a[x].rs);
pushup(x);
}
int query(int l,int r,int x){
if(a[x].l>=l&&a[x].r<=r)return a[x].sum;
pushdown(x);
int mid=(a[x].l+a[x].r)>>1,tot=0;
if(mid>=l)tot=tot+query(l,r,a[x].ls);
if(mid<r)tot=tot+query(l,r,a[x].rs);
return tot;
}
inline int sum(int x,int y){
int res=0;
while(top[x]!=top[y]){
if(d[top[x]<d[top[y]]])swap(x,y);
res=(res+query(idx[top[x]],idx[x],rt))%mod;
x=f[top[x]];
}
if(idx[x]>idx[y])swap(x,y);
return (res+query(idx[x],idx[y],rt))%mod;
}
inline void updates(int x,int y,int c){
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]])swap(x,y);
update(idx[top[x]],idx[x],c,rt);
x=f[top[x]];
}
if(idx[x]>idx[y])swap(x,y);
update(idx[x],idx[y],c,rt);
}
signed main(){
cin>>n>>m>>r>>mod;
for(int i=1;i<=n;i++)cin>>v[i];
for(int i=1;i<n;i++){
int x,y;
cin>>x>>y;
add(x,y),add(y,x);
}
cnt=0,dfs1(r),dfs2(r,r);
cnt=0;build(1,n,rt=cnt++);
for(int i=1;i<=m;i++){
int op,x,y,k;
cin>>op;
if(op==1){
cin>>x>>y>>k;
updates(x,y,k);
}else if(op==2){
cin>>x>>y;
cout<<sum(x,y)<<endl;
}else if(op==3){
cin>>x>>y;
update(idx[x],idx[x]+siz[x]-1,y,rt);
}else{
cin>>x;
cout<<query(idx[x],idx[x]+siz[x]-1,rt)<<endl;
}
}
return 0;
}