#include<bits/stdc++.h>
#define int long long
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
int mod,n,m,rt,p,x,y,r,e,s,op,cnt;
int a[100005],wson[100005],dep[100005],fa[100005],siz[100005],id[100005];
int wei[100005];//new id's weight
int top[100005];//the top of each chain
int sum[100005],tag[100005];//segment tree
int en[100005];
bool vis[100005];vector<int> t[100005];
void dfs1(int now,int dept,int fat){
vis[now]=1;siz[now]=1;dep[now]=dept;fa[now]=fat;
int w=0;
for(int i=0;i<t[now].size();i++){
if(vis[t[now][i]]) continue;
dfs1(t[now][i],dept+1,now);
siz[now]+=siz[t[now][i]];
if(w<siz[t[now][i]]){
w=siz[t[now][i]];
wson[now]=t[now][i];
}
}return;
}
void dfs2(int now,int rt){
//cout<<now<<' ';
vis[now]=1;
id[now]=++cnt;
en[cnt]=now;
wei[cnt]=a[now];
top[now]=rt;
if(!wson[now]) return;
dfs2(wson[now],rt);
for(int i=0;i<t[now].size();i++){
if(vis[t[now][i]]) continue;
dfs2(t[now][i],t[now][i]);
}return;
}
void update(int rt){
sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%mod;
return;
}
void build(int l,int r,int rt){
if(l==r){
sum[rt]=wei[l];
sum[rt]%=mod;
return;
}
int mid=(l+r)>>1;
build(lson);build(rson);
update(rt);
return;
}
void color(int l,int r,int rt,int k){
sum[rt]+=(r-l+1)*k;sum[rt]%=mod;
tag[rt]+=k;tag[rt]%=mod;
return;
}
void ph_tg(int l,int r,int rt){
if(tag[rt]!=0){
int mid=(l+r)>>1;
color(lson,tag[rt]);
color(rson,tag[rt]);
tag[rt]=0;
}
return;
}
void modify(int l,int r,int rt,int k){
//cout<<x<<' '<<y<<' '<<l<<' '<<r<<' '<<rt<<' '<<k<<endl;
if(x<=l&&r<=y){
color(l,r,rt,k);return;
}
ph_tg(l,r,rt);
int mid=(l+r)>>1;
if(x<=mid) modify(lson,k);
if(y>mid) modify(rson,k);
update(rt);
return;
}
int query(int l,int r,int rt){
if(x<=l&&r<=y){
return sum[rt];
}
int mid=(l+r)>>1,ans=0;
if(x<=l) ans=(ans+query(lson))%mod;
if(y>r) ans=(ans+query(rson))%mod;
return ans;
}
int query_path(int xx,int yy){
int ans=0;
while(top[xx]!=top[yy]){
if(dep[top[xx]]<dep[top[yy]]) swap(xx,yy);
x=id[top[xx]];y=yy;
ans=(ans+query(1,n,1))%mod;
xx=fa[top[xx]];
}
if(dep[xx]>dep[yy]) swap(xx,yy);
x=id[xx];y=id[yy];
ans=(ans+query(1,n,1))%mod;
return ans;
}
int query_son(int xx){
x=id[xx];y=id[xx]+siz[xx]-1;
return query(1,n,1);
}
void modify_path(int xx,int yy,int k){
k%=mod;
while(top[xx]!=top[yy]){
if(dep[top[xx]]<dep[top[y]]) swap(x,y);
x=id[top[xx]];y=id[xx];
modify(1,n,1,k);
xx=fa[top[xx]];
}
if(dep[xx]>dep[yy]) swap(xx,yy);
x=id[xx];y=id[yy];
modify(1,n,1,k);
return;
}
void modify_son(int xx,int k){
x=id[xx];y=id[xx]+siz[xx]-1;
//cout<<xx<<' '<<id[xx]<<' '<<siz[xx]<<endl;
modify(1,n,1,k);
return;
}
signed main(){
cin>>n>>m>>rt>>p;mod=p;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1,u,v;i<n;i++){
cin>>u>>v;
t[u].push_back(v);
t[v].push_back(u);
}
dfs1(rt,1,1);memset(vis,0,sizeof(vis));
dfs2(rt,rt);//Here is a pot
//cout<<endl;
build(1,n,1);
//for(int i=1;i<=n;i++){
// cout<<siz[i]<<' ';
//}cout<<endl;
for(int i=1;i<=n;i++){
cout<<id[i]<<' ';
}cout<<endl;
for(int i=1;i<=n*2;i++){
cout<<sum[i]<<' ';
}cout<<endl;
while(m--){//r--x e--y s--z
cin>>op>>r;
if(op==1){
cin>>e>>s;
modify_path(r,e,s);
}else if(op==2){
cin>>e;
cout<<query_path(r,e)<<endl;
}else if(op==3){
cin>>s;
modify_son(r,s);
}else{
cout<<query_son(r)<<endl;
}
}
return 0;
}