#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=1e5+10;
struct qwe
{
int net,to;
} E[2*maxn];
struct nod
{
int sum,laz,l,r,ls,rs,le;
} nod[2*maxn];
int rt,n,m,R,P,a[maxn],cnt,hea[maxn],f[maxn],d[maxn],siz[maxn],son[maxn],rk[maxn],top[maxn],id[maxn];
int x,y,z,bs,opt;
void add(int x,int y)
{
E[++bs].to=y;
E[bs].net=hea[x];
hea[x]=bs;
}
void push_up(int t)
{
nod[t].sum=((LL)nod[nod[t].ls].sum+(LL)nod[nod[t].rs].sum)%P;
}
void push_down(int t)
{
if(nod[t].ls)
{
nod[nod[t].ls].laz=((LL)nod[nod[t].ls].laz+(LL)nod[t].laz)%P;
nod[nod[t].ls].sum=((LL)nod[nod[t].ls].sum+(LL)nod[nod[t].ls].le*(LL)nod[t].laz%P)%P;
}
if(nod[t].rs)
{
nod[nod[t].rs].laz=((LL)nod[nod[t].rs].laz+(LL)nod[t].laz)%P;
nod[nod[t].rs].sum=((LL)nod[nod[t].rs].sum+(LL)nod[nod[t].rs].le*(LL)nod[t].laz%P)%P;
}
nod[t].laz=0;
}
void built(int t,int l,int r)
{
nod[t].l=l;
nod[t].r=r;
nod[t].le=r-l+1;
if(l==r)
{
nod[t].sum=a[rk[l]];
return;
}
int mid=(l+r)>>1;
nod[t].ls=t<<1;
built(nod[t].ls,l,mid);
if(mid<r)
{
nod[t].rs=t<<1|1;
built(nod[t].rs,mid+1,r);
}
if(nod[t].ls||nod[t].rs) push_up(t);
}
void xadd(int t,int x,int y,int z)
{
if(nod[t].l>=x&&nod[t].r<=y)
{
nod[t].laz=((LL)nod[t].laz+(LL)z)%P;
nod[t].sum=((LL)nod[t].sum+(LL)nod[t].le*(LL)z%P)%P;
return;
}
push_down(t);
if(nod[t].ls) xadd(nod[t].ls,x,y,z);
if(nod[t].rs) xadd(nod[t].rs,x,y,z);
if(nod[t].ls||nod[t].rs) push_up(t);
}
int query(int t,int x,int y)
{
int sum=0;
if(nod[t].l>=x&&nod[t].r<=y)
{
return nod[t].sum;
}
push_down(t);
if(nod[t].ls) sum=((LL)sum+(LL)query(nod[t].ls,x,y))%P;
if(nod[t].rs) sum=((LL)sum+(LL)query(nod[t].rs,x,y))%P;
if(nod[t].ls||nod[t].rs) push_up(t);
return sum;
}
void dfs1(int u,int fa,int dep)
{
f[u]=fa;
d[u]=dep;
siz[u]=1;
for(int i=hea[u];i;i=E[i].net)
{
int v=E[i].to;
if(v!=fa)
{
dfs1(v,u,dep+1);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])
{
son[u]=v;
}
}
}
}
void dfs2(int u,int t)
{
top[u]=t;
id[u]=++cnt;
rk[cnt]=u;
if(son[u]) dfs2(son[u],t);
for(int i=hea[u];i;i=E[i].net)
{
int v=E[i].to;
if(v!=son[u]&&v!=f[u])
{
dfs2(v,v);
}
}
return;
}
void fadd(int x,int y,int z)
{
if(d[top[x]]<d[top[y]])
{
swap(x,y);
}
while(top[x]!=top[y])
{
xadd(rt,id[top[x]],id[x],z);
x=f[top[x]];
if(d[top[x]]<d[top[y]])
{
swap(x,y);
}
}
if(id[x]>id[y])
{
swap(x,y);
}
xadd(rt,id[x],id[y],z);
}
int sum(int x,int y)
{
int ans=0;
if(d[top[x]]<d[top[y]])
{
swap(x,y);
}
while(top[x]!=top[y])
{
ans=((LL)ans+(LL)query(rt,id[top[x]],id[x]))%P;
x=f[top[x]];
if(d[top[x]]<d[top[y]])
{
swap(x,y);
}
}
if(id[x]>id[y])
{
swap(x,y);
}
ans=((LL)ans+(LL)query(rt,id[x],id[y]))%P;
return ans;
}
void tadd(int x,int y)
{
xadd(rt,id[x],id[x]+siz[x]-1,y);
}
int ssum(int x)
{
return query(rt,id[x],id[x]+siz[x]-1);
}
int main()
{
scanf("%d%d%d%d",&n,&m,&R,&P);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
rt=1;
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs1(R,R,1);
dfs2(R,R);
built(rt,1,n);
for(int i=1;i<=m;i++)
{
scanf("%d",&opt);
if(opt==1)
{
scanf("%d%d%d",&x,&y,&z);
fadd(x,y,z);
}
if(opt==2)
{
scanf("%d%d",&x,&y);
printf("%d\n",sum(x,y));
}
if(opt==3)
{
scanf("%d%d",&x,&y);
tadd(x,y);
}
if(opt==4)
{
scanf("%d",&x);
printf("%d\n",ssum(x));
}
}
return 0;
}