#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int n,m,h[N],ne[N*2],e[N*2],idx;
int w[N],nw[N];
int cnt,dfn[N];
int top[N];
int dep[N],fa[N],son[N],sz[N],mod;
int root;
struct Node
{
int l,r;
int sum,add;
#define ls p<<1
#define rs p<<1|1
}t[N*4];
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void pushdown(int p)
{
if(t[p].add){
t[ls].sum=(t[ls].sum+(ll)(t[ls].r-t[ls].l+1)*t[p].add)%mod;
t[rs].sum=(t[rs].sum+(ll)(t[rs].r-t[rs].l+1)*t[p].add)%mod;
t[ls].add+=t[p].add;
t[rs].add+=t[p].add;
// t[ls].add=(t[ls].add+t[p].add)%mod;
// t[rs].add=(t[rs].add+t[p].add)%mod;
t[p].add=0;
}
}
void pushup(int p){
t[p].sum=t[ls].sum+t[rs].sum;
}
void build(int p,int l,int r)
{
t[p]={l,r};
if(l==r){
t[p].sum=nw[l];
return ;
}
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(p);
}
void modify(int p,int tl,int tr,int k)
{
if(tl<=t[p].l&&t[p].r<=tr){
t[p].sum=(t[p].sum+(ll)(t[p].r-t[p].l+1)*k)%mod;
// t[p].add=(t[p].add+k)%mod;
t[p].add+=k;
return ;
}
pushdown(p);
int mid=t[p].l+t[p].r>>1;
if(tl<=mid){
modify(ls,tl,tr,k);
}
if(tr>mid){
modify(rs,tl,tr,k);
}
pushup(p);
}
int query(int p,int tl,int tr)
{
if(tl<=t[p].l&&t[p].r<=tr){
return t[p].sum;
}
pushdown(p);
int res=0;
int mid=t[p].l+t[p].r>>1;
if(tl<=mid){
res=query(ls,tl,tr);
}
if(tr>mid){
res=(res+query(rs,tl,tr))%mod;
}
return res%mod;
}
void dfs_2(int u,int t)
{
dfn[u]=++cnt,nw[cnt]=w[u],top[u]=t;
if(!son[u])return;
dfs_2(son[u],t);
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(j==fa[u]||j==son[u])continue;
dfs_2(j,j);
}
}
void dfs_1(int u,int father,int depth)
{
sz[u]=1,fa[u]=father,dep[u]=depth;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(j==father)continue;
dfs_1(j,u,depth+1);
sz[u]+=sz[j];
if(sz[son[u]]<sz[j]){
son[u]=j;//
}
}
}
void update_path(int u,int v,int k)
{
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
modify(1,dfn[top[u]],dfn[u],k);
u=fa[top[u]];
}
if(dep[u]<dep[v])swap(u,v);
modify(1,dfn[v],dfn[u],k);
}
int query_path(int u,int v)
{
int res=0;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
res=(res+query(1,dfn[top[u]],dfn[u]))%mod;
u=fa[top[u]];
}
if(dep[u]<dep[v])swap(u,v);
res=(res+query(1,dfn[v],dfn[u]))%mod;
return res%mod;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&root,&mod);
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++)scanf("%d",&w[i]);
for(int i=0;i<n-1;i++){
int a,b;
scanf("%d%d",&a,&b);
add(a,b);add(b,a);
}
dfs_1(root,-1,1);
dfs_2(root,1);
build(1,1,n);
while(m--){
int t,k,u,v;
scanf("%d%d",&t,&u);
if(t==1){
scanf("%d%d",&v,&k);
update_path(u,v,k);
}
else if(t==3){
scanf("%d",&k);
modify(1,dfn[u],dfn[u]+sz[u]-1,k);
}
else if(t==2){
scanf("%d",&v);
printf("%d\n",query_path(u,v)%mod);
}
else{
printf("%d\n",query(1,dfn[u],dfn[u]+sz[u]-1)%mod);
// cout<<query(1,dfn[u],dfn[u]+sz[u]-1)<<endl;
}
}
return 0;
}