#include<cstdio>
#define rr register
#define ll long long
using namespace std;
const ll N=310000;
const ll M=1240000;
ll n,m,Summ,R,P;
ll seg[N],rev[M],size[N],son[N],top[N],dep[N];
ll num[N],father[N],Max[N],tot;
ll first[M],next[M],go[M];
struct SegmentTree{
ll l,r,sum,add;
#define l(x) tree[x].l
#define r(x) tree[x].r
#define sum(x) tree[x].sum
#define add(x) tree[x].add
}tree[M];
inline void myswap(ll &x,ll &y){x^=y^=x^=y; return;}
inline void in_add(rr ll x,rr ll y){next[++tot]=first[x],first[x]=tot,go[tot]=y;}
inline void insert(rr ll x,rr ll y){in_add(x,y); in_add(y,x);}
inline ll get(){
rr char c;
while ((c=getchar())<'0'||c>'9'); rr ll res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
return res;
}
inline void write(rr ll x){if (x>9) write(x/10); putchar(x%10+48);}
inline void dfs1(rr ll u,rr ll f){
rr ll e,v;
size[u]=1;
father[u]=f;
dep[u]=dep[f]+1;
for(e=first[u];v=go[e],e;e=next[e])
if (v!=f){
dfs1(v,u);
size[u]+=size[v];
if (size[v]>size[son[u]]) son[u]=v;
}
return;
}
inline void dfs2(rr ll u,rr ll f){
rr ll e,v;
if (son[u]){
seg[son[u]]=++seg[0];
top[son[u]]=top[u];
rev[seg[0]]=son[u];
dfs2(son[u],u);
}
for(e=first[u];v=go[e],e;e=next[e])
if(!top[v]){
seg[v]=++seg[0];
rev[seg[0]]=v;
top[v]=v;
dfs2(v,u);
}
return;
}
inline void build(ll p,ll l,ll r){
l(p)=l,r(p)=r;
if (l==r) {sum(p)=num[rev[l]]; return;}
ll mid=l+r>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
sum(p)=sum(p<<1)+sum(p<<1|1);
return;
}
inline void spread(ll p){
if (add(p)){
sum(p<<1)+=add(p)*(r(p<<1)-l(p<<1)+1);
sum(p<<1|1)+=add(p)*(r(p<<1|1)-l(p<<1|1)+1);
add(p<<1)+=add(p);
add(p<<1|1)+=add(p);
add(p)=0;
}
return;
}
inline void change(ll p,ll l,ll r,ll d){
if (l<=l(p)&&r>=r(p)){
sum(p)+=d*(r(p)-l(p)+1);
add(p)+=d;
return;
}
spread(p);
ll mid=(l(p)+r(p))>>1;
if (r<=mid) change(p<<1,l,r,d);
if (l>mid) change(p<<1|1,l,r,d);
sum(p)=sum(p<<1)+sum(p<<1|1);
return;
}
inline ll query(ll p,ll l,ll r){
if (l<=l(p)&&r>=r(p)) return sum(p);
spread(p);
ll mid=(l(p)+r(p))>>1;
ll val=0;
if (r<=mid) val+=query(p<<1,l,r);
if (l>mid) val+=query(p<<1|1,l,r);
return val;
}
inline void ask(rr ll x,rr ll y){
rr ll fx=top[x],fy=top[y];
while(fx!=fy){
if (dep[fx]<dep[fy]) myswap(x,y),myswap(fx,fy);
Summ+=query(1,seg[fx],seg[x]);
Summ%=P;
x=father[fx]; fx=top[x];
}
if (dep[x]>dep[y]) myswap(x,y);
Summ+=query(1,seg[x],seg[y]);
Summ%=P;
return;
}
inline void change_range(ll x,ll y,ll z){
z%=P;
ll fx=top[x],fy=top[y];
while(fx!=fy){
if (dep[fx]<dep[fy]) myswap(x,y),myswap(fx,fy);
change(1,seg[fx],seg[x],z);
x=father[fx]; fx=top[x];
}
if (dep[x]>dep[y]) myswap(x,y);
change(1,seg[x],seg[y],z);
return;
}
inline void change_son(ll x,ll z){
change(1,seg[x],seg[x]+size[x]-1,z);
return;
}
inline void askson(ll x){
Summ=query(1,seg[x],seg[x]+size[x]-1);
return;
}
int main(){
rr ll i,j,k,u,v,s1,s2,sr,z;
n=get(); m=get(); R=get(); P=get();
for(i=1;i<=n;i++) num[i]=get();
for(i=1;i<n;i++) s1=get(),s2=get(),insert(s1,s2);
dfs1(R,0);
seg[0]=seg[R]=top[R]=rev[R]=1;
dfs2(R,0);
build(1,1,seg[0]);
for(i=1;i<=m;i++){
Summ=0;
sr=get();
if (sr==1) {
u=get(),v=get(),z=get(); change_range(u,v,z);
} else if (sr==2){
u=get(),v=get(); ask(u,v); write(Summ); putchar('\n');
} else if (sr==3){
u=get(),v=get(); change_son(u,v);
} else {
u=get(); askson(u); write(Summ); putchar('\n');
}
}
return 0;
}