#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
struct node{
int to,nxt;
}z[N];
struct tree{
int l,r,lazy,sum;
}t[4*N];
struct good{
int w,fa,top,id,d,son,maxson;
}l[N];
int n,m,root,mod,ans;
int h[N];
int a[N];
int w[N];
int cnt,res;
void add(int x,int y){
cnt++;
z[cnt].to=y;
z[cnt].nxt=h[x];
h[x]=cnt;
}
void dfs1(int x,int fa,int dis){
l[x].son=1;
l[x].fa=fa;
l[x].d=dis;
l[l[x].maxson].son=-1;
for(int i=h[x];i;i=z[i].nxt){
int y=z[i].to;
if(y==fa) continue;
dfs1(y,x,dis+1);
l[x].son+=l[y].son;
if(l[y].son>l[l[x].maxson].son) l[x].maxson=y,l[l[x].maxson].son=l[y].son;
}
}
void dfs2(int x,int topf){
l[x].id=++cnt;
w[cnt]=a[x];
l[x].top=topf;
if(!l[x].maxson)return;
dfs2(l[x].maxson,topf);
for(int i=h[x];i;i=z[i].nxt){
int y=z[i].to;
if(y==l[x].fa||y==l[x].maxson)continue;
dfs2(y,y);
}
}
void build(int l,int r,int p){
t[p].l=l;
t[p].r=r;
if(l==r){
t[p].sum=w[l];
t[p].sum%=mod;
return ;
}
int mid=(l+r)>>1;
build(l,mid,p*2);
build(mid+1,r,p*2+1);
t[p].sum=t[p*2].sum+t[p*2+1].sum;
t[p].sum%=mod;
}
void lazzy(int x){
if(t[x].lazy){
t[x*2].sum+=t[x].lazy*(t[x*2].r-t[x*2].l+1);
t[x*2+1].sum+=t[x].lazy*(t[x*2+1].r-t[x*2+1].l+1);
t[x*2].lazy+=t[x].lazy;
t[x*2+1].lazy+=t[x].lazy;
t[x*2].sum%=mod;
t[x*2+1].sum%=mod;
t[x*2+1].lazy%=mod;
t[x*2].lazy%=mod;
t[x].lazy=0;
}
}
int qury(int L,int R,int p){
int res=0;
if(t[p].l>=L&&t[p].r<=R) {
return t[p].sum;
}
lazzy(p);
int mid=t[p].l+t[p].r>>1;
if(L<=mid){
res+=qury(L,R,p*2);
}
if(R>mid){
res+=qury(L,R,p*2+1);
}
return res%mod;
}
void chan(int l,int r,int k,int p){
if(t[p].l>=l&&t[p].r<=r){
t[p].lazy+=k;
t[p].sum+=k*(t[p].r-t[p].l+1);
t[p].sum%=mod;
t[p].lazy%=mod;
return ;
}
lazzy(p);
int mid=t[p].r+t[p].l>>1;
if(l<=mid){
chan(l,r,k,p*2);
}
if(r>mid){
chan(l,r,k,p*2+1);
}
t[p].sum=(t[p*2].sum+t[p*2+1].sum)%mod;
}
int find(int x,int y){
int ans=0;
while(l[x].top!=l[y].top){
if(l[l[x].top].d<l[l[y].top].d){
swap(x,y);
}
ans+=qury(l[l[x].id].top,l[x].id,1);
ans=ans%mod;
x=l[l[x].top].fa;
}
if(l[x].d>l[y].d) swap(x,y);
ans+=qury(l[x].id,l[y].id,1);
return ans%mod;
}
void geng2(int x,int z){
chan(l[x].id,l[x].id+l[x].son-1,z,1);
}
void geng(int x,int y,int z){
z=z%mod;
while(l[x].top!=l[y].top){
if(l[l[x].top].d<l[l[y].top].d){
swap(x,y);
}
chan(l[l[x].id].top,l[x].id,z,1);
x=l[l[x].top].fa;
}
if(l[x].d>l[y].d){
swap(x,y);
}
chan(l[x].id,l[y].id,z,1);
}
int find2(int x){
ans=0;
ans=qury(l[x].id,l[x].id+l[x].son-1,1);
return ans%mod;
}
int main(){
scanf("%d%d%d%d",&n,&m,&root,&mod);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
a[i]%=mod;
}
for(int i=1;i<=n-1;i++){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs1(root,0,1);
cnt=0;
dfs2(root,root);
build(1,n,1);
for(int i=1;i<=m;i++){
int opt;
scanf("%d",&opt);
if(opt==1){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
geng(x,y,z);
}
if(opt==2){
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",find(x,y));
}
if(opt==3){
int x,z;
scanf("%d%d",&x,&z);
geng2(x,z);
}
if(opt==4){
int x;
scanf("%d",&x);
printf("%d\n",find2(x));
}
}
}