#include<iostream>
#include<algorithm>
using namespace std;
#define N 2000005
#define ll long long
#define Trfor(x) for(int i=Head[x];i;i=Next[i])
int Next[N],Head[N],End[N];ll Wt[N],id;
int deep[N],fa[N],son[N],sz[N];
int top[N],dfn[N],idx;
int n,m,r,p;
inline void add(int a,int b){
id++;End[id]=b,Next[id]=Head[a],Head[a]=id;
}
struct Tree{
int l,r;
ll sum,lazy;
int size() const{return r-l+1;}
}tr[N*4];
inline void pushup(int p){
tr[p].sum=tr[p<<1].sum+tr[p<<1|1].sum;
}
inline void pushdown(int p){
if(tr[p].lazy){
int pl=p<<1,pr=p<<1|1;
tr[pl].sum+=tr[pl].size()*tr[p].lazy;
tr[pr].sum+=tr[pr].size()*tr[p].lazy;
tr[pl].lazy+=tr[p].lazy;
tr[pr].lazy+=tr[p].lazy;
tr[p].lazy=0;
}
}
inline void build(int p,int l,int r){
tr[p].l=l;tr[p].r=r;
if(l==r){
tr[p].sum=Wt[dfn[l]];return;
}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
pushup(p);
}
inline void adds(int p,int l,int r,int v){
if(l<=tr[p].l&&tr[p].r<=r){
tr[p].sum+=v*tr[p].size();
tr[p].lazy+=v;
return;
}pushdown(p);
int mid=(tr[p].l+tr[p].r)>>1;
if(l<=mid) adds(p<<1,l,r,v);
if(r>mid) adds(p<<1|1,l,r,v);
pushup(p);
}
inline ll query(int p,int l,int r){
if(l<=tr[p].l&&tr[p].r<=r) return tr[p].sum;
pushdown(p);
int mid=(tr[p].l+tr[p].r)>>1;ll ans=0;
if(l<=mid) ans+=query(p<<1,l,r);
if(r>mid) ans+=query(p<<1|1,l,r);
return ans%p;
}
inline void dfs1(int x){
sz[x]=1;ll mx=0;
Trfor(x){
int y=End[i];
if(y==fa[x]) continue;
fa[y]=x;deep[y]=deep[x]+1;
dfs1(y);
if(sz[y]>mx) mx=sz[y],son[x]=y;
sz[x]+=sz[y];
}
}
inline void dfs2(int x){
dfn[x]=++idx;
if(!son[x]) return;
top[son[x]]=top[x];
dfs2(son[x]);
Trfor(x){
int y=End[i];
if(y==fa[x]||y==son[x]) continue;
top[y]=y;
dfs2(y);
}
}
inline void tradd(int x,int y,int v){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) swap(x,y);
adds(1,dfn[top[x]],dfn[x],v);
x=fa[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
adds(1,dfn[x],dfn[y],v);
}
inline ll ask(int x,int y){
ll ans=0;
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) swap(x,y);
ans+=query(1,dfn[top[x]],dfn[x]);ans%=p;
x=fa[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
ans+=query(1,dfn[x],dfn[y]);ans%=p;
return ans;
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);std::cout.tie(0);
cin>>n>>m>>r>>p;
for(int i=1;i<=n;i++){
cin>>Wt[i];
}
for(int i=1;i<n;i++){
int a,b;cin>>a>>b;
add(a,b);add(b,a);
}
deep[r]=1;dfs1(r);top[r]=r;dfs2(r);build(1,1,n);
for(int i=1;i<=m;i++){
int opt,x,y,z;
cin>>opt;
switch(opt){
case(1):{
cin>>x>>y>>z;
tradd(x,y,z);
break;
}
case(2):{
cin>>x>>y;
cout<<ask(x,y)%p<<"\n";
break;
}
case(3):{
cin>>x>>z;
adds(1,dfn[x],dfn[x]+sz[x]-1,z);
break;
}
case(4):{
cin>>x;
cout<<query(1,dfn[x],dfn[x]+sz[x]-1)%p<<"\n";
break;
}
}
}
return 0;
}