#include<bits/stdc++.h>
#define ll long long int
const int N=5e6+7;
using namespace std;
struct tree{
int to,next,w;
}edge[2*N];
int n,m,r,mod;
int head[N],cnt,deep[N],sum[N],ch[N];
int top[N],fa[N],son[N],number,size[N],val[N],lazy[N],id[N];
void add_edge(int u,int v){
cnt++;
edge[cnt].to=v,edge[cnt].next=head[u],head[u]=cnt;
}
void dfs1(int u,int v){
deep[u]=deep[v]+1;
fa[u]=v;
size[u]=1;
for (int i=head[u];i!=0;i=edge[i].next){
int j=edge[i].to;
if (j==v){
continue;
}
dfs1(j,u);
size[u]+=size[j];
if (size[j]>size[son[u]]){
son[u]=j;
}
}
}
void dfs2(int u,int v){
number++;
id[u]=number,val[number]=u,top[u]=v;
if (!son[u]){
return ;
}
dfs2(son[u],v);
for (int i=head[u];i!=0;i=edge[i].next){
int j=edge[i].to;
if (j!=fa[u] && j!=son[u]){
dfs2(j,j);
}
}
return ;
}
void build(int u,int l,int r){
if (l==r){
sum[l]=ch[val[u]];
return ;
}
int mid=(l+r)>>1;
build(2*u,l,mid);
build(2*u+1,mid+1,r);
sum[u]+=sum[2*u]+sum[2*u+1];
sum[u]%=mod;
return ;
}
void push(int u,int l,int r){
int mid=(l+r)>>1;
lazy[2*u]+=lazy[u];lazy[2*u]%=mod;
lazy[2*u+1]+=lazy[u];lazy[2*u+1]%=mod;
sum[2*u]+=lazy[u]*(mid-l+1);sum[2*u]%=mod;
sum[2*u+1]+=lazy[u]*(r-mid);sum[2*u]%=mod;
lazy[u]=0;
return ;
}
void update(int u,int s,int t,int l,int r,int k){
if (l<=s && r>=t){
sum[u]+=k*(t-s+1);sum[u]%=mod;
lazy[u]+=k;lazy[u]%=mod;
return ;
}
if(s>r||t<l)return ;
int mid=(s+t)>>1;
if (lazy[u]!=0){
push(u,s,t);
}
if (l>=mid){
update(2*u,s,mid,l,r,k);
}
if (r>mid){
update(2*u+1,mid+1,t,l,r,k);
}
sum[u]=(sum[2*u]+sum[2*u+1])%mod;
return ;
}
ll query(int u,int s,int t,int l,int r){
if (l<=s && r>=t){
return sum[u]%=mod;
}
if(s>r|| t<l) return 0;
int mid=(s+t)>>1;
ll ans=0;
if (mid>=l){
ans+=query(2*u,s,mid,l,r);
ans%=mod;
}
if (r>mid){
ans+=query(2*u+1,mid+1,t,l,r);
ans%=mod;
}
return ans%=mod;
}
ll query_sum(int u,int v){
ll ans=0;
while (top[u]!=top[v]){
if (deep[top[u]]<deep[top[v]]){
swap(u,v);
}
ans+=query(1,1,number,id[top[u]],id[u]);
u=fa[top[u]];
}
if (id[u]<id[v]){
swap(u,v);
}
ans+=query(1,1,number,id[v],id[u]);
return ans;
}
void update_path(int u,int v,int k){
while (top[u]!=top[v]){
if (deep[u]<deep[v]){
swap(u,v);
}
update(1,1,number,id[top[u]],id[u],k);
u=fa[top[u]];
}
if (id[u]<id[v]){
swap(u,v);
}
update(1,1,number,id[v],id[u],k);
}
int main()
{
int n,m,r,mod;
cin>>n>>m>>r>>mod;
for (int i=1;i<=n;i++){
cin>>ch[i];
}
for (int i=1;i<=n-1;i++){
int x,y;
cin>>x>>y;
add_edge(x,y),add_edge(y,x);
}
dfs1(r,0);
dfs2(r,r);
build(1,1,n);
while (m--){
int t,x,y,z;
cin>>t;
if (t==1){
cin>>x>>y>>z;
}
if (t==2){
cin>>x>>y;
}
if (t==3){
cin>>x>>y;
}
if (t==4){
cin>>x;
}
}
return 0;
}