#include<bits/stdc++.h>
#define lc (p*2)
#define rc (p*2+1)
#define N 1000005
using namespace std;
int n,m;
int mod;
int deep[N],fa[N],top[N];
int hc[N],w[N],ti,id[N],node[N],s,size[N];
int head[2*N],next[2*N],to[2*N],cnt;
struct Node{
int data;
int tag;
int l;
int r;
}t[N*4];
void push_up(int p){
t[p].data=t[lc].data+t[rc].data;
t[p].data%=mod;
return;
}
void build(int p,int l,int r){
t[p].l=l;
t[p].r=r;
if(l==r){
t[p].data=w[node[l]];
t[p].data%=mod;
return;
}
int mid=(l+r)>>1;
build(lc,l,mid);
build(rc,mid+1,r);
push_up(p);
}
void push_down(int p){
t[lc].data+=(t[lc].r-t[lc].l+1)*t[p].tag;
t[lc].data%=mod;
t[lc].tag+=t[p].tag;
t[lc].tag%=mod;
t[rc].data+=(t[rc].r-t[rc].l+1)*t[p].tag;
t[rc].data%=mod;
t[rc].tag+=t[p].tag;
t[rc].tag%=mod;
t[p].tag=0;
}
void change(int p,int l,int r,int ll,int rr,int z){
if(ll<=l&&r<=rr){
t[p].tag+=z;
t[p].tag%=mod;
t[p].data+=(r-l+1)*z;
t[p].data%=mod;
return;
}
push_down(p);
int mid=(l+r)>>1;
if(mid>=ll) change(lc,l,mid,ll,rr,z);
if(mid<rr) change(rc,mid+1,r,ll,rr,z);
push_up(p);
}
int ask(int p,int l,int r,int ll,int rr){
if(ll<=l&&r<=rr){
return t[p].data;
}
push_down(p);
int ans=0;
int mid=(l+r)>>1;
if(mid>=ll) ans+=ask(lc,l,mid,ll,rr);
if(mid<rr) ans+=ask(rc,mid+1,r,ll,rr);
return ans%mod;
}
void add(int u,int v){
++cnt;
to[cnt]=v;
next[cnt]=head[u];
head[u]=cnt;
}
void dfs1(int u,int fath,int d){
deep[u]=d;
fa[u]=fath;
for(int i=head[u];i;i=next[i]){
int v=to[i];
if(v!=fath){
dfs1(v,u,d+1);
hc[u]=w[hc[u]]<w[v]?v:hc[u];
}
}
}
void dfs2(int u,int fath,int topf){
id[u]=++ti;
size[u]=1;
node[id[u]]=u;
top[u]=topf;
if(hc[u]==0){
return;
}
dfs2(hc[u],u,topf);
size[u]+=size[hc[u]];
for(int i=head[u];i;i=next[i]){
int v=to[i];
if(v!=fath&&v!=hc[u]){
dfs2(v,u,v);
size[u]+=size[v];
}
}
}
void LCA_add(int x,int y,int z){
if(deep[x]>deep[y]){
swap(x,y);
}
if(top[x]==top[y]){
change(1,1,n,id[x],id[y],z);
return;
}
while(top[x]!=top[y]){
if(deep[top[x]]>deep[top[y]]){
swap(x,y);
}
change(1,1,n,id[top[y]],id[y],z);
y=fa[top[y]];
}
if(deep[x]>deep[y]){
swap(x,y);
}
change(1,1,n,id[x],id[y],z);
return;
}
int LCA_ask(int x,int y){
int ans=0;
if(deep[x]>deep[y]){
swap(x,y);
}
if(top[x]==top[y]){
ans+=ask(1,1,n,id[x],id[y]);
return ans%mod;
}
while(top[x]!=top[y]){
if(deep[top[x]]>deep[top[y]]){
swap(x,y);
}
ans+=ask(1,1,n,id[top[y]],id[y]);
ans%=mod;
y=fa[top[y]];
}
if(deep[x]>deep[y]){
swap(x,y);
}
ans+=ask(1,1,n,id[x],id[y]);
return ans%mod;
}
void s_change(int x,int z){
change(1,1,n,id[x],id[x]+size[x]-1,z);
return;
}
int s_ask(int x){
return ask(1,1,n,id[x],id[x]+size[x]-1);
}
int main(){
w[0]=-2147483647;
cin>>n>>m>>s>>mod;
for(int i=1;i<=n;i++){
scanf("%d",&w[i]);
}
for(int i=1;i<=n-1;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs1(s,0,1);
dfs2(s,0,s);
build(1,1,n);
for(int i=1;i<=m;i++){
int opt,x,y,z;
scanf("%d%d",&opt,&x);
if(opt==1){
scanf("%d%d",&y,&z);
LCA_add(x,y,z);
}
if(opt==2){
scanf("%d",&y);
printf("%d\n",LCA_ask(x,y));
}
if(opt==3){
scanf("%d\n",&z);
s_change(x,z);
}
if(opt==4){
printf("%d\n",s_ask(x));
}
}
return 0;
}