#include<cstdio>
#include<iostream>
using namespace std;
inline int read(){
int f=1,ans=0;
char t=getchar();
while(!isdigit(t)){
if(t=='-')f=-1;
t=getchar();
}
while(isdigit(t)){
ans=(ans<<1)+(ans<<3)+t-'0';
t=getchar();
}
return ans*f;
}
int a[200001],head[200001],num,p;
struct s
{
int next,to;
} s[200001];
struct sgtree
{
int l,r,tag;
long long sum1;
}sg[400001];
inline void add1(int x,int y)
{
num++;
s[num].next=head[x];
s[num].to=y;
head[x]=num;
return ;
}
int fa[100001],top[100001],seg[100001],rev[100001],size[100001],son[100001],dep[100001],tot,ll[100001],rr[100001];
void dfs1(int str,int f)
{
fa[str]=f;
dep[str]=dep[f]+1;
for(int i=head[str];i;i=s[i].next)
{
if(s[i].to!=f)
{
dfs1(s[i].to,str);
size[str]+=size[s[i].to];
if(size[s[i].to]>size[son[str]])son[str]=s[i].to;
}
}
return;
}
void dfs2(int str)
{
if(son[fa[str]]!=str)top[str]=str;
else top[str]=top[fa[str]];
seg[str]=++tot;
rev[tot]=str;
ll[str]=tot;
if(son[str])dfs2(son[str]);
for(int i=head[str];i;i=s[i].next)
{
if(s[i].to!=fa[str]&&s[i].to!=son[str])
dfs2(s[i].to);
}
rr[str]=tot;
return ;
}
inline void build(int x,int l,int r)
{
sg[x].l=l;sg[x].r=r;
if(l==r)
{
sg[x].sum1=a[rev[l]];
if(sg[x].sum1>p)sg[x].sum1%=p;
sg[x].tag=0;
return ;
}
int mid=(l+r)>>1;
build(2*x,l,mid);
build(2*x+1,mid+1,r);
sg[x].sum1=(sg[2*x].sum1+sg[2*x+1].sum1)%p;
}
inline void pushdown(int x)
{
sg[2*x].tag+=sg[x].tag;
sg[2*x+1].tag+=sg[x].tag;
sg[2*x].sum1=(sg[2*x].sum1+(sg[2*x].r-sg[2*x].l+1)*sg[x].tag)%p;
sg[2*x+1].sum1=(sg[2*x+1].sum1+(sg[2*x+1].r-sg[2*x+1].l+1)*sg[x].tag)%p;
// cout<<sg[2*x].l<<' '<<sg[2*x].r<<' '<<sg[2*x].sum1<<endl;
// cout<<sg[2*x+1].l<<' '<<sg[2*x+1].r<<' '<<sg[2*x+1].sum1<<endl;
sg[x].tag=0;
return ;
}
inline void modify(int x,int l,int r,int v)
{
if(sg[x].l>r||sg[x].r<l)return ;
if(sg[x].r<=r&&sg[x].l>=l)
{
sg[x].sum1=(sg[x].sum1+(sg[x].r-sg[x].l+1)*v)%p;
// cout<<l<<' '<<r<<' '<<sg[x].sum1<<endl;
sg[x].tag+=v;
return;
}
int mid=(sg[x].l+sg[x].r)>>1;
if(sg[x].tag)
pushdown(x);
if(mid>=l)modify(2*x,l,r,v);
if(mid<r)modify(2*x+1,l,r,v);
sg[x].sum1=(sg[2*x].sum1+sg[2*x+1].sum1)%p;
// cout<<sg[x].l<<' '<<sg[x].r<<' '<<sg[x].sum1<<endl;
}
inline int query(int x,int l,int r)
{
// cout<<sg[x].l<<' '<<sg[x].r<<endl;
if(sg[x].l>r||sg[x].r<l){
// cout<<sg[x].l<<' '<<sg[x].r<<'a'<<endl;
return 0;
}
if(sg[x].l>=l&&sg[x].r<=r){
// cout<<sg[x].l<<' '<<sg[x].r<<endl;
return sg[x].sum1;
}
int mid=(sg[x].l+sg[x].r)>>1;
if(sg[x].tag)
pushdown(x);
long long ans=0;
if(mid>=l)ans=(ans+query(2*x,l,r))%p;
if(mid<r)ans=(ans+query(2*x+1,l,r))%p;
sg[x].sum1=(sg[2*x].sum1+sg[2*x+1].sum1)%p;
return ans;
}
inline void smodify(int x,int y,int v)
{
while(top[x]!=top[y])
{
if(dep[x]<dep[y])swap(x,y);
modify(1,seg[top[x]],seg[x],v);
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
modify(1,seg[y],seg[x],v);
return;
}
inline int squery(int x,int y)
{
long long ans=0;
while(top[x]!=top[y])
{
if(dep[x]<dep[y])swap(x,y);
ans=(ans+query(1,seg[top[x]],seg[x]))%p;
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
ans=(ans+query(1,seg[y],seg[x]))%p;
return ans;
}
int main()
{
int n=read(),m=read(),r=read(),ch;
p=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<n;i++)
{
int x,y;
x=read();y=read();
add1(x,y);
add1(y,x);
}
dfs1(r,0);
dfs2(r);
// for(int i=1;i<=n;i++)cout<<seg[i]<<' ';
// cout<<endl;
build(1,1,tot);
for(int i=1;i<=m;i++)
{
ch=read();
int x,y,v;
if(ch==1)
{
x=read();y=read();v=read();
smodify(x,y,v);
}
else if(ch==2)
{
x=read();y=read();
printf("%lld\n",squery(x,y));
}
else if(ch==3)
{
x=read();v=read();
// cout<<ll[x]<<' '<<rr[x]<<endl;
modify(1,ll[x],rr[x],v);
}
else
{
x=read();
printf("%lld\n",query(1,ll[x],rr[x]));
}
}
return 0;
}