#include<bits/stdc++.h>
#define int long long
#define ls p<<1
#define rs p<<1|1
using namespace std;
const int N=2e5+205;
int a[N];
int n,m,root,mod;
int fa[N],dep[N],siz[N],son[N];
int dfn[N],top[N],rnk[N];
struct Edge{
int to,next;
}edge[N];
struct SGT{
int l,r,sum,add;
}t[N<<2];
inline int read(){
int x=0,f=1;
char c=getchar_unlocked();
while(!isdigit(c)){
if(c=='-')f*=-1;
c=getchar_unlocked();
}
while(isdigit(c)){
x=(x<<3)+(x<<1)+(c^48);
c=getchar_unlocked();
}
return x*f;
}
inline void update(int p){t[p].sum=(t[ls].sum%mod+t[rs].sum%mod)%mod;}
inline void build(int l,int r,int p){
t[p].l=l,t[p].r=r;
if(l==r){
t[p].sum=a[rnk[l]]%mod;
return;
}
int mid=(l+r)>>1;
build(l,mid,ls);
build(mid+1,r,rs);
update(p);
}
inline void spread(int p){
t[p].add%=mod;
t[ls].sum=(t[ls].sum%mod+t[p].add%mod)%mod;
t[rs].sum=(t[rs].sum%mod+t[p].add%mod)%mod;
t[ls].add=(t[ls].add%mod+t[p].add%mod)%mod;
t[rs].add=(t[rs].add%mod+t[p].add%mod)%mod;
t[p].add=0;
return;
}
inline void modify(int l,int r,int p,int k){
k%=mod;
if(t[p].l>=l&&t[p].r<=r){
t[p].sum+=k;
t[p].add+=k;
t[p].sum%=mod;
t[p].add%=mod;
return;
}
spread(p);
int mid=(t[p].l+t[p].r)>>1;
if(l<=mid)modify(l,r,ls,k);
if(r>mid)modify(l,r,rs,k);
update(p);
}
inline int query(int l,int r,int p){
int ans=0;
if(t[p].l>=l&&t[p].r<=r)
return t[p].sum%mod;
spread(p);
int mid=(t[p].l+t[p].r)>>1;
if(l<=mid)ans+=query(l,r,ls),ans%=mod;
if(r>mid)ans+=query(l,r,rs),ans%=mod;
update(p);
ans%=mod;
return ans;
}
int head[N],cnt;
inline void add(int x,int y){
edge[++cnt].to=y;
edge[cnt].next=head[x];
head[x]=cnt;
}
inline void dfs1(int u,int f){
fa[u]=f;
dep[u]=dep[f]+1;
siz[u]=1;son[u]=-1;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==f)continue;
dfs1(v,u);
siz[u]+=siz[v];
if(son[u]==-1||siz[son[u]]<siz[v])son[u]=v;
}
}
int tot;
inline void dfs2(int u,int topf){
top[u]=topf;
++tot;
dfn[u]=tot;
rnk[tot]=u;
if(son[u]==-1)return;
dfs2(son[u],topf);
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==fa[u])continue;
if(v!=son[u]&&v!=fa[u])dfs2(v,v);
}
}
inline void Pathmodify(int u,int v,int k){
k%=mod;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
modify(dfn[top[u]],dfn[u],1,k);
u=fa[top[u]];
}
if(dep[top[u]]<dep[top[u]])swap(u,v);
modify(dep[u],dep[v],1,k);
}
inline int Pathquery(int u,int v){
int ans=0;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
ans+=query(dfn[top[u]],dfn[u],1);
ans%=mod;
u=fa[top[u]];
}
if(dep[top[u]]<dep[top[u]])swap(u,v);
ans+=query(dfn[u],dfn[v],1)%mod;
ans%=mod;
return ans;
}
inline void Nodemodify(int x,int k){
k%=mod;
modify(dfn[x],dfn[x]+siz[x]-1,1,k);
return;
}
inline int Nodequery(int x){
return query(dfn[x],dfn[x]+siz[x]-1,1)%mod;
}
signed main(){
n=read(),m=read(),root=read(),mod=read();
for(int i=1;i<=n;i++)
a[i]=read(),a[i]%=mod;
int u,v;
for(int i=1;i<=n;i++)
son[i]=-1;
for(int i=1;i<n;i++){
u=read(),v=read();
add(u,v),add(v,u);
}
int opt,x,y,z;
dfs1(root,0);
dfs2(root,0);
build(1,n,1);
for(int i=1;i<=m;i++){
opt=read();
switch(opt){
case 1:{
x=read(),y=read(),z=read();
Pathmodify(x,y,z);
break;
}
case 2:{
x=read(),y=read();
cout<<Pathquery(x,y)%mod<<"\n";
break;
}
case 3:{
x=read(),z=read();
Nodemodify(x,z);
break;
}
case 4:{
x=read();
cout<<Nodequery(x)%mod<<"\n";
break;
}
}
}
}