#include<bits/stdc++.h>
using namespace std;
#define int long long
#define re register
#define l(p) tree[p].l
#define r(p) tree[p].r
#define sum(p) tree[p].sum
//#define dat(p) tree[p].dat
#define add(p) tree[p].add
#define mul(p) tree[p].mul
const int sz=1e5+5;
int read()
{
char c;
int f=1,r=0;
c=getchar();
while(c!='-'&&(c<'0'||c>'9'))
c=getchar();
if(c=='-')
{
f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
r=r*10+c-'0';
c=getchar();
}
return r*f;
}
int mod;
int ns[sz],a[sz];
struct node
{
int to,nxt;
}e[sz*2];
int head[sz],cnt=1,sum1;
struct node1
{
int dep,f,siz,hc,id,ns,top;
}t[sz];
struct node2
{
int l,r,add,mul=1,dat,sum,col1,col2;
}tree[sz*4];
void build(int l,int r,int p)
{
l(p)=l;
r(p)=r;
if(l==r)
{
//dat(p)=a[ns[l]];
sum(p)=a[ns[l]];
return;
}
int mid=(l+r)/2;
build(l,mid,2*p);
build(mid+1,r,2*p+1);
sum(p)=(sum(2*p)+sum(2*p+1))%mod;
}
void add_edge(int x,int y)
{
e[cnt].to=y;
e[cnt].nxt=head[x];
head[x]=cnt++;
}
void dfs1(int now,int fa)
{
t[now].dep=(t[fa].dep+1)%mod,t[now].f=fa,t[now].siz=1;
int maxx=0;
for(int i=head[now];i;i=e[i].nxt)
{
if(e[i].to==fa)
continue;
dfs1(e[i].to,now);
t[now].siz=(t[now].siz+t[e[i].to].siz)%mod;
if(t[e[i].to].siz>maxx)
{
maxx=t[e[i].to].siz;
t[now].hc=e[i].to;
}
}
}
void dfs2(int now,int topp)
{
t[now].id=++sum1;
ns[sum1]=now;
t[now].top=topp;
if(!t[now].hc)
return;
dfs2(t[now].hc,topp);
for(int i=head[now];i;i=e[i].nxt)
{
if(e[i].to==t[now].f||e[i].to==t[now].hc)
continue;
dfs2(e[i].to,e[i].to);
}
}
void spread(int p)
{
sum(2*p)=(sum(2*p)*mul(p)%mod+add(p)*(r(2*p)-l(2*p)+1)%mod)%mod;
sum(2*p+1)=(sum(2*p+1)*mul(p)%mod+add(p)*(r(2*p+1)-l(2*p+1)+1)%mod)%mod;
//dat(2*p)=dat(2*p)*mul(p);
//dat(2*p+1)=dat(2*p+1)*mul(p);
add(2*p)=(add(2*p)*mul(p)%mod+add(p))%mod;
add(2*p+1)=(add(2*p+1)*mul(p)%mod+add(p))%mod;
mul(2*p)*=mul(p);
mul(2*p+1)*=mul(p);
add(p)=0;
mul(p)=1;
}
void change_add(int l,int r,int d,int p)
{
if(l<=l(p)&&r>=r(p))
{
sum(p)=(sum(p)+(r(p)-l(p)+1)*d%mod)%mod;
// dat(p)+=d;
add(p)=(add(p)+d)%mod;
return;
}
spread(p);
int mid=(l(p)+r(p))/2;
if(mid>=l)
change_add(l,r,d,2*p);
if(mid<r)
change_add(l,r,d,2*p+1);
sum(p)=(sum(2*p)+sum(2*p+1))%mod;
//dat(p)=max(dat(2*p),dat(2*p+1));
}
/*void change_mul(int l,int r,int d,int p)
{
if(l<=l(p)&&r(p)<=r)
{
sum(p)*=d;
// dat(p)*=d;
add(p)*=d;
mul(p)*=d;
return;
}
spread(p);
int mid=(l(p)+r(p))/2;
if(mid>=l)
change_mul(l,r,d,2*p);
if(mid<r)
change_mul(l,r,d,2*p+1);
sum(p)=sum(2*p)+sum(2*p+1);
// dat(p)=max(dat(2*p),dat(2*p+1));
}*/
/*int ask_dat(int l,int r,int p)
{
if(l<=l(p)&&r>=r(p))
return dat(p);
int ans=0;
int mid=(l(p)+r(p))/2;
if(mid>=l)
ans+=ask_dat(l,r,2*p);
if(mid<r)
ans+=ask_sum(l,r,2*p+1);
return ans;
}*/
int ask_sum(int l,int r,int p)
{
if(l<=l(p)&&r>=r(p))
return sum(p);
spread(p);
int ans=0;
int mid=(l(p)+r(p))/2;
if(mid>=l)
ans=(ans+ask_sum(l,r,2*p))%mod;
if(mid<r)
ans=(ans+ask_sum(l,r,2*p+1))%mod;
return ans;
}
signed main()
{
int n=read(),m=read(),r=read();
mod=read();
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<n;i++)
{
int x=read(),y=read();
add_edge(x,y);
add_edge(y,x);
}
dfs1(r,r);
dfs2(r,r);
build(1,n,1);
for(int i=1;i<=m;i++)
{
char c;
cin>>c;
if(c=='1')
{
int x=read(),y=read(),z=read();
while(t[x].top^t[y].top)
{
if(t[t[x].top].dep<t[t[y].top].dep)
swap(x,y);
change_add(t[x].id,t[t[x].top].id,z,1);
x=t[t[x].top].f;
}
if(t[x].id>t[y].id)
swap(x,y);
change_add(t[x].id,t[y].id,z,1);
}
if(c=='2')
{
int x=read(),y=read();
int ans=0;
while(t[x].top^t[y].top)
{
if(t[t[x].top].dep<t[t[y].top].dep)
{
swap(x,y);
}
ans=(ans+ask_sum(t[x].id,t[t[x].top].id,1))%mod;
x=t[t[x].top].f;
// cout<<ans<<endl;
}
if(t[x].id>t[y].id)
swap(x,y);
ans=(ans+ask_sum(t[x].id,t[y].id,1))%mod;
cout<<ans<<endl;
}
if(c=='3')
{
int x=read(),z=read();
change_add(t[x].id,t[x].id+t[x].siz-1,z,1);
}
if(c=='4')
{
int x=read();
cout<<ask_sum(t[x].id,t[x].id+t[x].siz-1,1)<<endl;
}
}
}