#include<bits/stdc++.h>
using namespace std;
#define mid ((t[i].l+t[i].r)>>1)
typedef long long ll;
struct node{
ll l,r,v,lazy;
}t[400005];
ll n,m,s,mod,f[100005],sz[100005],dep[100005],son[100005],id[100005],val[100005],a[100005],cnt,top[100005];
vector<int>e[100005];
void dfs1(int u,int fa){
f[u]=fa;
sz[u]=1;
dep[u]=dep[fa]+1;
for(auto v:e[u]){
if(v==fa)continue;
dfs1(v,u);
if(sz[v]>sz[son[u]])son[u]=v;
sz[u]+=sz[v];
}
}
void dfs2(int u,int tp){
id[u]=++cnt;
val[cnt]=a[u];
top[u]=tp;
if(son[u])dfs2(son[u],tp);
for(auto v:e[u]){
if(v!=son[u]&&v!=f[u]){
dfs2(v,v);
}
}
}
void build(int l,int r,int i){
t[i].l=l,t[i].r=r;
if(l==r){
t[i].v=val[l]%mod;
return ;
}
build(l,mid,i<<1);
build(mid+1,r,i<<1|1);
t[i].v=(t[i<<1].v+t[i<<1|1].v)%mod;
}
void pushdown(int i){
if(t[i].lazy){
t[i<<1].lazy=(t[i<<1].lazy+t[i].lazy)%mod;
t[i<<1|1].lazy=(t[i<<1|1].lazy+t[i].lazy)%mod;
t[i<<1].v=(t[i<<1].v+t[i].lazy*(t[i<<1].r-t[i<<1].l+1))%mod;
t[i<<1|1].v=(t[i<<1|1].v+t[i].lazy*(t[i<<1|1].r-t[i<<1|1].l+1))%mod;
t[i].lazy=0;
}
}
void update(int l,int r,int k,int i){
if(t[i].l>=l&&t[i].r<=r){
t[i].lazy=k%mod;
t[i].v=(t[i].v+k*(t[i].r-t[i].l+1))%mod;
return ;
}
if(t[i].r<l||t[i].l>r)return ;
pushdown(i);
update(l,r,k,i<<1);
update(l,r,k,i<<1|1);
t[i].v=(t[i*2].v+t[i*2+1].v)%mod;
}
ll ask(int l,int r,int i){
if(t[i].l>=l&&t[i].r<=r){
return t[i].v%mod;
}
if(t[i].r<l||t[i].l>r)return 0;
pushdown(i);
return (ask(l,r,i<<1)+ask(l,r,i<<1|1))%mod;
}
void add(int a,int b,int k){
while(top[a]!=top[b]){
if(dep[top[a]]<dep[top[b]])swap(a,b);
update(id[top[a]],id[a],k,1);
a=f[top[a]];
}
if(dep[a]>dep[b])update(id[b],id[a],k,1);
else update(id[a],id[b],k,1);
}
ll query(int a,int b){
ll sum=0;
while(top[a]!=top[b]){
if(dep[top[a]]<dep[top[b]])swap(a,b);
sum=(sum+ask(id[top[a]],id[a],1))%mod;
a=f[top[a]];
}
if(dep[a]>dep[b])sum=(sum+ask(id[b],id[a],1))%mod;
else sum=(sum+ask(id[a],id[b],1))%mod;
return sum;
}
int main(){
cin>>n>>m>>s>>mod;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
e[x].push_back(y),e[y].push_back(x);
}
dfs1(s,0);
dfs2(s,s);
build(1,n,1);
while(m--){
int ch;
scanf("%d",&ch);
if(ch==1){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
else if(ch==2){
int x,y;
scanf("%d%d",&x,&y);
printf("%lld\n",query(x,y));
}
else if(ch==3){
int x,y;
scanf("%d%d",&x,&y);
update(id[x],id[x]+sz[x]-1,y,1);
}
else{
int x;
scanf("%d",&x);
printf("%lld\n",ask(id[x],id[x]+sz[x]-1,1));
}
}
return 0;
}