#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
#define lson k<<1
#define rson k<<1|1
const int N=2e6+5;
struct tre{
int l,r,w,size,f;
}T[N];
int mod;
vector<int> e[N];
int n,m,root,dep[N],fa[N],son[N],tot[N],top[N],idx[N];
int val[N],cnt,a[N],b[N];
int dfs1(int u,int f,int deep)
{
dep[u]=deep;
fa[u]=f;
tot[u]=1;
int maxson=-1;
for(auto v:e[u])
{
if(v==f) continue;
tot[u]+=dfs1(v,u,deep+1);
if(tot[v]>maxson)
{
maxson=tot[v];
son[u]=v;
}
}
return tot[u];
}
void dfs2(int now,int topf)
{
idx[now]=++cnt;
a[cnt]=b[now];
top[now]=topf;
if(!son[now])
{
return ;
}
dfs2(son[now],topf);
for(auto v:e[now])
{
if(!idx[v])
{
dfs2(v,v);
}
}
return ;
}
void push_up(int k)
{
T[k].w=(T[lson].w+T[rson].w+mod)%mod;
return ;
}
void build(int k,int l,int r)
{
T[k].l=l,T[k].r=r;
T[k].size=r-l+1;
if(l==r)
{
T[k].w=a[l];
return ;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
push_up(k);
return ;
}
void push_down(int k)
{
if(T[k].f)
{
T[lson].w=(T[lson].w+T[lson].size*T[k].f)%mod;
T[rson].w=(T[rson].w+T[rson].size*T[k].f)%mod;
T[lson].f=(T[k].f+T[lson].f)%mod;
T[rson].f=(T[k].f+T[rson].f)%mod;
T[k].f=0;
}
return ;
}
void Inadd(int k,int l,int r,int val)
{
if(l<=T[k].l&&r>=T[k].r)
{
T[k].w+=T[k].size*val;
T[k].f+=val;
return ;
}
push_down(k);
int mid=(T[k].l+T[k].r)>>1;
if(l<=mid)
{
Inadd(lson,l,r,val);
}
if(r>mid)
{
Inadd(rson,l,r,val);
}
push_up(k);
return ;
}
void Treeadd(int x,int y,int val)
{
while(top[x]!=top[y])
{
if(dep[top[x]<dep[top[y]]])
{
swap(x,y);
}
Inadd(1,idx[top[x]],idx[x],val);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
Inadd(1,idx[x],idx[y],val);
return ;
}
int Insum(int k,int l,int r)
{
int ans=0;
if(l<=T[k].l&&r>=T[k].r)
{
return T[k].w;
}
push_down(k);
int mid=(T[k].l+T[k].r)>>1;
if(l<=mid)
{
ans=(ans+Insum(lson,l,r))%mod;
}
if(r>mid)
{
ans=(ans+Insum(rson,l,r))%mod;
}
return ans;
}
void Treesum(int x,int y)
{
int ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans=(ans+Insum(1,idx[top[x]],idx[x]))%mod;
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ans=(ans+Insum(1,idx[x],idx[y]))%mod;
printf("%d\n",ans);
return ;
}
int main()
{
// freopen("P3384_1.in","r",stdin);
scanf("%d%d%d%d",&n,&m,&root,&mod);
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
for(int i=1;i<=n-1;i++)
{
int u,v;
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
dfs1(root,0,1);
dfs2(root,root);
build(1,1,n);
for(int i=1;i<=m;i++)
{
int opt,x,y,z;
scanf("%d",&opt);
switch(opt)
{
case 1:{
scanf("%d%d%d",&x,&y,&z);
Treeadd(x,y,z);
break;
}
case 2:{
scanf("%d%d",&x,&y);
Treesum(x,y);
break;
}
case 3:{
scanf("%d%d",&x,&z);
Inadd(1,idx[x],idx[x]+tot[x]-1,z%mod);
break;
}
case 4:{
scanf("%d",&x);
printf("%d\n",Insum(1,idx[x],idx[x]+tot[x]-1));
break;
}
}
}
return 0;
}