#include <bits/stdc++.h>
using namespace std;
#define ll long long
struct tree{ll v,late;}t[100010<<2];
int n,m,r,mod,val[100010],p[100010],size[100010],deep[100010],son[100010],top[100010];
int dfn[100010],tot,id[100010],cnt[100010];
vector<int> G[100010];
void make_tree(int u,int fa){
size[u]=1;
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(v==fa)continue;
p[v]=u;
deep[v]=deep[u]+1;
make_tree(v,u);
size[u]+=size[v];
if(size[v]>size[son[u]])son[u]=v;
}
}
void make_son(int u,int fa){
top[u]=fa;
dfn[u]=++tot; id[tot]=u;
if(son[u])make_son(son[u],fa);
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(v!=p[u] && v!=son[u])make_son(v,v);
}
cnt[u]=tot;
}
void build_tree(int o,int l,int r){
if(l==r){t[o].v=val[id[l]]; return;}
int mid=l+r>>1;
build_tree(o<<1,l,mid);
build_tree(o<<1|1,mid+1,r);
t[o].v=t[o<<1].v+t[o<<1|1].v;
}
void push_down(int o,int l,int r){
t[o<<1].late+=t[o].late;
t[o<<1|1].late+=t[o].late;
int mid=l+r>>1;
t[o<<1].v+=t[o].late*(mid-l+1);
t[o<<1|1].v+=t[o].late*(r-mid);
t[o].late=0;
}
void update(int o,int l,int r,int L,int R,int v){
if(L<=l && r<=R){
t[o].late+=v;
t[o].v+=(r-l+1)*v;
return;
}
if(t[o].late)push_down(o,l,r);
ll mid=l+r>>1;
if(mid>=L)update(o<<1,l,mid,L,R,v);
if(mid<R)update(o<<1|1,mid+1,r,L,R,v);
t[o].v=t[o<<1].v+t[o<<1|1].v;
}
ll quire(int o,int l,int r,int L,int R){
if(L<=l && r<=R)return t[o].v;
if(t[o].late)push_down(o,l,r);
int mid=l+r>>1;
ll ans=0;
if(L<=mid)ans+=quire(o<<1,l,mid,L,R);
if(mid<R)ans+=quire(o<<1|1,mid+1,r,L,R);
return ans;
}
void add(){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
while(top[x]!=top[y]){
if(deep[top[y]]>deep[top[x]])swap(x,y);
update(1,1,tot,dfn[top[x]],dfn[x],z);
x=p[top[x]];
}
if(deep[y]>deep[x])swap(x,y);
update(1,1,tot,dfn[y],dfn[x],z);
}
void get_answer(){
int x,y;
ll ans=0;
scanf("%d%d",&x,&y);
while(top[x]!=top[y]){
if(deep[top[y]]>deep[top[x]])swap(x,y);
ans+=quire(1,1,tot,dfn[top[x]],dfn[x]);
ans%=mod;
x=p[top[x]];
}
if(deep[y]>deep[x])swap(x,y);
ans+=quire(1,1,tot,dfn[y],dfn[x]);
printf("%lld\n",ans%mod);
}
void add_son(){
int x,z;
scanf("%d%d",&x,&z);
update(1,1,tot,dfn[x],cnt[x],z);
}
void get_son(){
int x;
scanf("%d",&x);
ll ans=quire(1,1,tot,dfn[x],cnt[x]);
printf("%lld\n",ans%mod);
}
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;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
p[r]=r;
make_tree(r,r);
make_son(r,r);
build_tree(1,1,tot);
while(m--){
int q;
scanf("%d",&q);
if(q==1)add();
if(q==2)get_answer();
if(q==3)add_son();
if(q==4)get_son();
}
return 0;
}