#include <bits/stdc++.h>
#define MAXN 100005
#define mod 10007
#define IINF 0x3f3f3f3f
#define LINF 0x7fffffffffffffff
#define LL long long
#define ULL unsigned long long
using namespace std;
int n,m,root,md;
LL w[MAXN];
vector<int> g[MAXN];
int size1[MAXN],son[MAXN],depth[MAXN],fa[MAXN];
int top[MAXN],id[MAXN],rev[MAXN],cnt;
LL s[4*MAXN],add[MAXN];
void dfs1(int u){
size1[u]=1;
depth[u]=depth[fa[u]]+1;
for(int i=0;i<g[u].size();i++){
int v=g[u][i];
if(v!=fa[u]){
fa[v]=u;
dfs1(v);
size1[u]+=size1[v];
if(size1[son[u]]<size1[v]) son[u]=v;
}
}
}
void dfs2(int u,int tp){
top[u]=tp;
id[u]=++cnt,rev[cnt]=u;
if(son[u]) dfs2(son[u],tp);
for(int i=0,v;i<g[u].size();i++){
v=g[u][i];
if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
}
void up(int p){s[p]=(s[p*2]+s[p*2+1])%md;}
void down(int p,int l,int r){
if(!add[p]) return ;
int mid=l+r>>1;
add[p*2]=(add[p*2]+add[p])%md;
s[p*2]=(s[p*2]+(LL)(mid-l+1)*add[p]%md)%md;
add[p*2+1]=(add[p*2+1]+add[p])%md;
s[p*2+1]=(s[p*2+1]+(LL)(r-mid)*add[p]%md)%md;
}
void build(int p,int l,int r){
add[p]=0;
if(l==r){
s[p]=w[rev[l]];
return ;
}
int m=(l+r)>>1;
build(p*2,l,m); build(p*2+1,m+1,r);
up(p);
return ;
}
void update(int p,int l,int r,int x,int y,int v){
if(y<l||x>r) return ;
if(l==r){
s[p]=(s[p]+v*(l-r+1)%md)%md;
add[p]=(add[p]+v)%md;
return ;
}
down(p,l,r);
int m=(l+r)>>1;
update(p*2,l,m,x,y,v); update(p*2+1,m+1,r,x,y,v);
up(p);
return ;
}
LL query_sum(int p,int l,int r,int x,int y){
if(y<l||x>r) return 0;
if(x<=l&&r<=y){
return s[p];
}
down(p,l,r);
int m=(l+r)>>1;
LL ret=0;
ret=(query_sum(p*2,l,m,x,y)+ret)%md;
ret=(query_sum(p*2+1,m+1,r,x,y)+ret)%md;
return ret%md;
}
void ans_add(int u,int v,int qwq){
while(top[u]!=top[v]){
if(depth[top[u]]<depth[top[v]]) swap(u,v);
update(1,1,n,id[top[u]],id[u],qwq);
u=fa[top[u]];
}
if(id[u]>id[v]) swap(u,v);
update(1,1,n,id[u],id[v],qwq);
}
LL ans_sum(int u,int v){
LL ret=0;
while(top[u]!=top[v]){
if(depth[top[u]]<depth[top[v]]) swap(u,v);
ret=(ret+query_sum(1,1,n,id[top[u]],id[u]))%md;
u=fa[top[u]];
}
if(id[u]>id[v]) swap(u,v);
ret=(ret+query_sum(1,1,n,id[u],id[v]))%md;
return ret%md;
}
int main(){
scanf("%d%d%d%d",&n,&m,&root,&md);
for(int i=1;i<=n;i++) scanf("%lld",&w[i]);
for(int i=1,u,v;i<n;i++){
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
dfs1(root);
dfs2(root,root);
build(1,1,n);
for(int i=1,op,x,y,v;i<=m;i++){
scanf("%d",&op);
if(op==1){
scanf("%d%d%d",&x,&y,&v);
ans_add(x,y,v%md);
}else if(op==2){
scanf("%d%d",&x,&y);
printf("%lld\n",ans_sum(x,y)%md);
}else if(op==3){
scanf("%d%d",&x,&v);
update(1,1,n,id[x],id[x]+size1[x]-1,v%md);
}else if(op==4){
scanf("%d",&x);
printf("%lld\n",query_sum(1,1,n,id[x],id[x]+size1[x]-1)%md);
}
}
return 0;
}