#include<iostream>
#include<cstdio>
#include<vector>
#define int long long
using namespace std;
int n,m,r,p,cnt;
vector<int>e[100010];
int val[100010];
int sz[100010],fa[100010],d[100010],hs[100010],id[100010],rk[100010],tp[100010];
int ad[400010],vl[400010];
void dfs1(int x)
{
sz[x]=1;
d[x]=d[fa[x]]+1;
hs[x]=-1;
for(int i=0;i<e[x].size();i++)
{
if(e[x][i]!=fa[x])
{
fa[e[x][i]]=x;
dfs1(e[x][i]);
sz[x]+=sz[e[x][i]];
if(hs[x]==-1||sz[hs[x]]<sz[e[x][i]])
{
hs[x]=e[x][i];
}
}
}
}
void dfs2(int x,int top)
{
tp[x]=top;
id[x]=++cnt;
rk[cnt]=x;
if(hs[x]==-1)
{
return;
}
dfs2(hs[x],top);
for(int i=0;i<e[x].size();i++)
{
if(e[x][i]!=fa[x]&&e[x][i]!=hs[x])
{
dfs2(e[x][i],e[x][i]);
}
}
}
void add(int o,int l,int r,int il,int ir,int iv)
{
if(il>ir)
{
swap(il,ir);
}
if(l>=il&&r<=ir)
{
ad[o]=(ad[o]+iv)%p;
}
else
{
if(il<=(l+r>>1))
{
add(o<<1,l,(l+r>>1),il,ir,iv);
}
if(ir>(l+r>>1))
{
add((o<<1)^1,(l+r>>1)+1,r,il,ir,iv);
}
}
vl[o]=0;
if(l<r)
{
vl[o]=(vl[o<<1]+vl[(o<<1)^1])%p;
}
vl[o]=(vl[o]+(r-l+1)*ad[o]%p)%p;
}
int query(int o,int l,int r,int il,int ir,int sv)
{
if(il>ir)
{
swap(il,ir);
}
if(l>=il&&r<=ir)
{
return (vl[o]+sv*(r-l+1))%p;
}
int cn=0;
if(il<=(l+r>>1))
{
cn+=query(o<<1,l,(l+r>>1),il,ir,sv+ad[o]);
}
if(ir>(l+r>>1))
{
cn+=query((o<<1)^1,(l+r>>1)+1,r,il,ir,sv+ad[o]);
}
return cn%p;
}
void treeadd(int l,int r,int v)
{
while(tp[l]!=tp[r])
{
if(d[l]<d[r])
{
swap(l,r);
}
add(1,1,n,id[tp[l]],id[l],v);
l=fa[tp[l]];
}
if(d[l]>d[r])
{
swap(l,r);
}
add(1,1,n,id[l],id[r],v);
}
int treeask(int l,int r)
{
int cnt=0;
while(tp[l]!=tp[r])
{
if(d[l]<d[r])
{
swap(l,r);
}
cnt+=query(1,1,n,id[tp[l]],id[l],0);
l=fa[tp[l]];
}
if(d[l]>d[r])
{
swap(l,r);
}
cnt+=query(1,1,n,id[l],id[r],0);
return cnt%p;
}
signed main()
{
cin>>n>>m>>r>>p;
for(int i=1;i<=n;i++)
{
cin>>val[i];
}
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
fa[r]=r;
dfs1(r);
dfs2(r,r);
for(int i=1;i<=n;i++)
{
add(1,1,n,id[i],id[i],val[i]);
}
for(int i=1;i<=m;i++)
{
int op;
cin>>op;
if(op==1)
{
int x,y,z;
cin>>x>>y>>z;
treeadd(x,y,z);
}
if(op==2)
{
int x,y;
cin>>x>>y;
cout<<treeask(x,y)<<endl;
}
if(op==3)
{
int x,y;
cin>>x>>y;
add(1,1,n,id[x],id[x]+sz[x]-1,y);
}
if(op==4)
{
int x;
cin>>x;
cout<<query(1,1,n,id[x],id[x]+sz[x]-1,0)<<endl;
}
}
return 0;
}