#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
struct node{
int a,lz;
}tree[200000];
int v[200000],w[200000],next[200000],last[200000],num,nw[200000],id[200000];
int son[200000],top[200000],deep[200000],size[200000],fa[200000];
int n,m,r,p;
void add(int x,int y)
{
num++;
v[num]=y;
next[num]=last[x];
last[x]=num;
}
void dfs1(int root,int ff,int de)
{
fa[root]=ff;
deep[root]=de;
size[root]=1;
int maxson=0;
for(int i=last[root];i;i=next[i])
{
if(deep[v[i]]!=0) continue;
dfs1(v[i],root,de+1);
size[root]+=size[v[i]];
if(size[v[i]]>maxson) son[root]=v[i];
}
}
void dfs2(int root,int topp)
{
num++;
top[root]=topp;
nw[num]=w[root];
id[root]=num;
if(son[root]!=0) dfs2(son[root],topp);
for(int i=last[root];i;i=next[i])
{
if (top[v[i]]!=0) continue;
dfs2(v[i],v[i]);
}
}
void buildtree(int root,int l,int r)
{
if(l>r) return;
if(l==r){ tree[root].a=nw[l]; return;}
int mid=(r+l)/2;
buildtree(root*2,l,mid);
buildtree(root*2+1,mid+1,r);
tree[root].a=(tree[root*2].a+tree[root*2+1].a)%p;
}
void putdown(int root,int l,int r)
{
if(tree[root].lz!=0)
{
tree[root*2].lz+=tree[root].lz;
tree[root*2+1].lz+=tree[root].lz;
int mid=(l+r)/2;
tree[root*2].a=(tree[root*2].a%p+tree[root].lz*(mid-l+1)%p)%p;
tree[root*2+1].a=(tree[root*2+1].a%p+tree[root].lz*(r-mid)%p)%p;
tree[root].lz=0;
}
return;
}
void treechange(int root,int l,int r,int s,int t,int ad)
{
if(s<=l && r<=t)
{
tree[root].lz+=ad;
tree[root].a=(tree[root].a+(r-l+1)*ad)%p;
return;
}
putdown(root,l,r);
int mid=(l+r)/2;
if (mid>=s)
treechange(root*2,l,mid,s,t,ad);
if (mid+1<=t)
treechange(root*2+1,mid+1,r,s,t,ad);
tree[root].a=(tree[root*2].a+tree[root*2+1].a)%p;
return;
}
int treefind(int root,int l,int r,int s,int t)
{
if(l>=s && r<=t)
return tree[root].a;
if(r<s || l>t) return 0;
putdown(root,l,r);
int ans=0,mid=(l+r)/2;
if(mid>=s) ans=(ans%p+treefind(root*2,l,mid,s,t)%p)%p;
if(mid+1<=t) ans=(ans%p+treefind(root*2+1,mid+1,r,s,t)%p)%p;
return ans%p;
}
void change1(int x,int y,int z)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
treechange(1,1,n,id[top[x]],id[x],z);
x=fa[top[x]];
}
if(deep[x]<deep[y]) swap(x,y);
treechange(1,1,n,id[y],id[x],z);
}
int find1(int x,int y,int z)
{
int ans=0;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
ans=(ans+treefind(1,1,n,id[top[x]],id[x]))%p;
x=fa[top[x]];
}
if(deep[x]<deep[y]) swap(x,y);
ans=(ans+treefind(1,1,n,id[y],id[x]))%p;
return ans;
}
void change2(int x,int z){
treechange(1,1,n,id[x],id[x]+size[x]-1,z);
}
int find2(int x){
int ans=0;
ans=treefind(1,1,n,id[x],id[x]+size[x]-1)%p;
return ans;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&r,&p);
for(int i=1;i<=n;i++)
scanf("%d",&w[i]);
for(int i=1;i<=n-1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs1(r,0,1);
num=0;
dfs2(r,r);
buildtree(1,1,n);
for(int i=1;i<=m;i++)
{
int t,x,y,z;
scanf("%d",&t);
if(t==1)
{
scanf("%d%d%d",&x,&y,&z);
change1(x,y,z);
}
if(t==2)
{
scanf("%d%d",&x,&y);
int ans=find1(x,y,z);
printf("%d\n",ans%p);
}
if(t==3)
{
scanf("%d%d",&x,&z);
change2(x,z);
}
if(t==4)
{
scanf("%d",&x);
int ans=find2(x);
printf("%d\n",ans%p);
}
}
}