#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int mod,tot;
int val[100001],siz[100001],son[100001],fa[100001],dep[100001];
int num[100001],top[100001],nval[100001];
vector<int> l[100001];
struct Node{
int val,add,l,r;
#define v(x) tr[x].val
#define d(x) tr[x].add
#define l(x) tr[x].l
#define r(x) tr[x].r
}tr[400001];
void build(int x,int l,int r){
l(x)=l;
r(x)=r;
if(l==r){
v(x)=nval[l];
return;
}
int mid=(l+r)>>1;
build(2*x,l,mid);
build(2*x+1,mid+1,r);
v(x)=(v(2*x)+v(x*2+1))%mod;
}
void push_down(int x){
if(d(x)){
v(x*2)=(v(x*2)+d(x)*(r(x*2)-l(x*2)+1));
v(x*2+1)=(v(x*2+1)+d(x)*(r(x*2+1)-l(x*2+1)+1));
d(x*2)+=d(x);
d(x*2+1)+=d(x);
d(x)=0;
}
}
void change(int x,int l,int r,int v){
if(l(x)>=l && r(x)<=r){
v(x)=(v(x)+v*(r-l+1))%mod;
d(x)+=v;
return;
}
push_down(x);
int mid=(l(x)+r(x))>>1;
if(l<=mid) change(x*2,l,r,v);
if(r>mid) change(x*2+1,l,r,v);
v(x)=(v(2*x)+v(x*2+1))%mod;
}
int query(int x,int l,int r){
if(l(x)>=l && r(x)<=r)return v(x);
push_down(x);
int ans=0,mid=(l(x)+r(x))>>1;
if(l<=mid) ans+=query(x*2,l,r);
if(r>mid) ans+=query(x*2+1,l,r);
return ans%mod;
}
void dfs1(int x,int root,int d){
siz[x]++;
fa[x]=root;
dep[x]=d;
for(int i=0;i<l[x].size();i++){
int u=l[x][i];
if(u==root) continue;
dfs1(u,x,d+1);
siz[x]+=siz[u];
if(siz[u]>siz[son[x]]) son[x]=u;
}
}
void dfs2(int x,int topx){
num[x]=++tot;
nval[tot]=val[x];
top[x]=topx;
if(!son[x]) return;
dfs2(son[x],topx);
for(int i=0;i<l[x].size();i++){
int u=l[x][i];
if(u==son[x] || u==fa[x]) continue;
dfs2(u,u);
}
}
void updroad(int u,int v,int x){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
change(1,num[top[u]],num[u],x);
u=fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
change(1,num[u],num[v],x);
}
int queryroad(int u,int v){
int ans=0;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
ans=(ans+query(1,num[u],num[top[u]]))%mod;
u=fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
ans=(ans+query(1,num[u],num[v]))%mod;
return ans;
}
int main(){
int n,u,v,x,jud,m,root;
cin>>n>>m>>root>>mod;
for(int i=1;i<=n;i++){
cin>>val[i];
val[i]=val[i]%mod;
}
for(int i=1;i<=n-1;i++){
cin>>u>>v;
l[u].push_back(v);
l[v].push_back(u);
}
dfs1(root,0,1);
dfs2(root,root);
build(1,1,n);
for(int i=1;i<=m;i++){
cin>>jud;
if(jud==1){
cin>>u>>v>>x;
updroad(u,v,x);
}
if(jud==2){
cin>>u>>v;
cout<<queryroad(u,v)<<endl;
}
if(jud==3){
cin>>u>>x;
change(1,num[u],num[u]+siz[u]-1,x);
}
if(jud==4){
cin>>u;
cout<<query(1,num[u],num[u]+siz[u]-1)<<endl;
}
}
}