#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5+10;
int n,m,r,mod;
int val[N];
int dfn[N],top[N],rk[N];
int dep[N],fa[N],size[N],son[N];
struct node{
int l,r,ls,rs,sum,lazy;
}a[N<<4];
struct edge{
int next,to;
}e[N<<4];
int head[N],cnt;
void add(int u,int v){
e[++cnt]=(edge){head[u],v};
head[u]=cnt;
}
void dfs1(int x){
size[x]=1;
dep[x]=dep[fa[x]]+1;
for(int v,i=head[x];i;i=e[i].next){
v=e[i].to;
if(dep[v]) continue;
fa[v]=x;
dfs1(v);
size[x]+=size[v];
if(size[v]>size[son[x]]) son[x]=v;
}
}
void dfs2(int x,int t){
top[x]=t;
dfn[x]=++cnt;
rk[cnt]=x;
if(son[x]) dfs2(son[x],t);
for(int i=head[x],v;i;i=e[i].next){
v=e[i].to;
if(v==fa[x]) continue;
if(son[x]!=v) dfs2(v,v);
}
}
void pushup(int o){a[o].sum=(a[a[o].ls].sum+a[a[o].rs].sum)%mod;}
void build(int o,int l,int r){
if(l==r){
a[o].sum=val[rk[l]];
a[o].l=a[o].r=l;
return ;
}
int mid=(l+r)>>1;
a[o].ls=++cnt,a[o].rs=++cnt;
build(a[o].ls,l,mid);
build(a[o].rs,mid+1,r);
a[o].l=a[a[o].ls].l;
a[o].r=a[a[o].rs].r;
pushup(o);
}
void pushdown(int o){
if(a[o].lazy){
int ls=a[o].ls,rs=a[o].rs;
a[ls].lazy=(a[ls].lazy+a[o].lazy)%mod;
a[rs].lazy=(a[rs].lazy+a[o].lazy)%mod;
a[ls].sum=(a[ls].sum+(a[ls].r-a[ls].l+1)*a[o].lazy)%mod;
a[rs].sum=(a[rs].sum+(a[rs].r-a[rs].l+1)*a[o].lazy)%mod;
a[o].lazy=0;
}
}
void updata(int o,int x,int y,int d){
if(a[o].l>=x&&a[o].r<=y){
a[o].lazy+=d;
a[o].sum=(a[o].sum+(a[o].r-a[o].l+1)*d)%mod;
return ;
}
pushdown(o);
int mid=(a[o].l+a[o].r)>>1;
if(x<=mid) updata(a[o].ls,x,y,d);
if(y>mid) updata(a[o].rs,x,y,d);
pushup(o);
}
int query(int o,int x,int y){
if(a[o].l>=x&&a[o].r<=y) return a[o].sum;
pushdown(o);
int mid=(a[o].l+a[o].r)>>1;
int rel=0;
if(x<=mid) rel=(rel+query(a[o].ls,x,y))%mod;
if(y>mid) rel=(rel+query(a[o].rs,x,y))%mod;
return rel;
}
int getsum(int x,int y){
int rel=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
rel=(rel+query(1,dfn[top[x]],dfn[x]))%mod;
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
rel=(rel+query(1,dfn[x],dfn[y]))%mod;
return rel;
}
int change(int x,int y,int d){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
updata(1,dfn[top[x]],dfn[x],d);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
updata(1,dfn[x],dfn[y],d);
}
int main()
{
scanf("%d%d%d%d",&n,&m,&r,&mod);
for(int i=1;i<=n;++i) scanf("%d",&val[i]);
for(int i=1,x,y;i<n;++i){
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
cnt=0,dfs1(r),dfs2(r,r);
build(1,1,n);
for(int i=1,op,x,y,z;i<=m;++i){
scanf("%d",&op);
if(op==1){
scanf("%d%d%d",&x,&y,&z);
change(x,y,z);
}
if(op==2){
scanf("%d%d",&x,&y);
printf("%d
",getsum(x,y));
}
if(op==3){
scanf("%d%d",&x,&z);
updata(1,dfn[x],dfn[x]+size[x]-1,z);
}
if(op==4){
scanf("%d",&x);
printf("%d
",query(1,dfn[x],dfn[x]+size[x]-1));
}
}
return 0;
}