#include<bits/stdc++.h>
#define MAXN 100010
#define ll long long
using namespace std;
ll n,m,r,p,cnt,mod;
ll top[MAXN],val[MAXN],dep[MAXN],son[MAXN],fa[MAXN],size[MAXN],a[MAXN],id[MAXN],tree[4*MAXN],tag[MAXN];
vector<ll> g[MAXN],child[MAXN];
void build(ll now,ll l,ll r)
{
if(l==r)
{
tree[now]=val[l]%mod;
return;
}
ll mid=(l+r)>>1;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
tree[now]=(tree[now<<1]+tree[now<<1|1])%mod;
}
void pushdown(ll now,ll l,ll r)
{
tag[now<<1]=(tag[now]+tag[now<<1])%mod;
tag[now<<1|1]=(tag[now]+tag[now<<1|1])%mod;
ll mid=(l+r)>>1;
tree[now<<1]=(tree[now<<1]+(mid-l+1)*tag[now]%mod)%mod;
tree[now<<1|1]=(tree[now<<1|1]+(r-mid)*tag[now]%mod)%mod;
tag[now]=0;
}
void modify(ll now,ll l,ll r,ll ql,ll qr,ll v)
{
//cout<<l<<"kkk"<<r<<' '<<ql<<' '<<qr<<endl;
if(ql<=l&&qr>=r)
{
tree[now]=(tree[now]+v*(r-l+1)%mod)%mod;
tag[now]=(tag[now]+v)%mod;
return;
}
pushdown(now,l,r);
ll mid=(l+r)>>1;
if(ql<=mid) modify(now<<1,l,mid,ql,qr,v);
if(mid<qr) modify(now<<1|1,mid+1,r,ql,qr,v);
tree[now]=(tree[now<<1]+tree[now<<1|1])%mod;
}
ll query(ll now,ll l,ll r,ll ql,ll qr)
{
//cout<<l<<"kkk"<<r<<ql<<qr<<endl;
if(ql<=l&&qr>=r) return tree[now];
pushdown(now,l,r);
ll mid=(l+r)>>1;
ll ans=0;
if(ql<=mid) ans=(ans+query(now<<1,l,mid,ql,qr))%mod;
if(mid<qr) ans=(ans+query(now<<1|1,mid+1,r,ql,qr))%mod;
return ans%mod;
}
void dfs1(ll u,ll y)
{
dep[u]=dep[y]+1;
size[u]=1;
fa[u]=y;
ll maxn=0;
for(ll i=0;i<g[u].size();i++)
{
ll v=g[u][i];
if(v==y) continue;
child[u].push_back(v);
dfs1(v,u);
size[u]+=size[v];
if(size[v]>maxn) son[u]=v,maxn=size[v];
}
}
void dfs2(ll u,ll topf)
{
id[u]=++cnt;
val[cnt]=a[u];
top[u]=topf;
if(!son[u]) return;
dfs2(son[u],topf);
for(ll i=0;i<child[u].size();i++)
{
ll v=child[u][i];
if(v!=son[u]) dfs2(v,v);
}
}
ll query1(ll x,ll y)
{
ll ans=0;
while(top[x]!=top[y])
{
//cout<<x<<' '<<y<<' '<<top[x]<<' '<<top[y]<<endl;
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans=(ans+query(1,1,n,id[top[x]],id[x]))%mod;
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
//cout<<x<<y;
ans=(ans+query(1,1,n,id[x],id[y]))%mod;
return ans%mod;
}
ll query2(ll x)
{
return query(1,1,n,id[x],id[x]+size[x]-1)%mod;
}
void modify1(ll x,ll y,ll v)
{
ll ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
modify(1,1,n,id[top[x]],id[x],v);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
modify(1,1,n,id[x],id[y],v);
}
void modify2(ll x,ll v)
{
modify(1,1,n,id[x],id[x]+size[x]-1,v);
}
int main()
{
//freopen("P3384_1.in","r",stdin);
//freopen("P3384","w",stdout);
cin>>n>>m>>r>>p;mod=p;
for(ll i=1;i<=n;i++) cin>>a[i];
for(ll i=1;i<n;i++)
{
ll u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs1(r,r);
dfs2(r,r);
build(1,1,n);
//for(ll i=1;i<=n;i++) cout<<fa[i]<<endl;
for(ll i=1;i<=m;i++)
{
ll num,x,y,z;
cin>>num;
if(num==1)
{
cin>>x>>y>>z;
modify1(x,y,z%mod);
}
if(num==2)
{
cin>>x>>y;
cout<<query1(x,y)%mod<<endl;
}
if(num==3)
{
cin>>x>>z;
modify2(x,z%mod);
}
if(num==4)
{
cin>>x;
cout<<query2(x)%mod<<endl;
}
}
return 0;
}