#include<bits/stdc++.h>
using namespace std;
const int N=1e5+50;
#define int long long
int n,m,x,y,k,cnt,root,mod;
int fa[N],w[N],size[N],dep[N],son[N],top[N],id[N],wt[N];
vector<int>a[N];
struct tree{
int l,r,val,lan;
}t[N*4];
void build(int l,int r,int pre){
t[pre].l=l,t[pre].r=r;
if(l==r){
t[pre].val=wt[l];
return;
}
int mid=l+r>>1;
build(l,mid,pre*2);
build(mid+1,r,pre*2+1);
t[pre].val=(t[pre*2].val+t[pre*2+1].val)%mod;
return;
}
void spread(int pre){
t[pre*2].lan=t[pre*2].lan+t[pre].lan;
t[pre*2+1].lan=t[pre*2+1].lan+t[pre].lan;
t[pre*2].val=(t[pre*2].val+t[pre].lan*(t[pre*2].r-t[pre*2].l+1))%mod;
t[pre*2+1].val=(t[pre*2+1].val+t[pre].lan*(t[pre*2+1].r-t[pre*2+1].l+1))%mod;
t[pre].lan=0;
}
void add(int pre){
if(x<=t[pre].l&&t[pre].r<=y){
t[pre].val=(t[pre].val+k*(t[pre].r-t[pre].l+1))%mod;
t[pre].lan=(t[pre].lan+k)%mod;
return;
}
spread(pre);
if(x<=t[pre*2].r)add(pre*2);
if(t[pre*2+1].l<=y)add(pre*2+1);
t[pre].val=(t[pre*2].val+t[pre*2+1].val)%mod;
return;
}
int search(int pre){
if(x<=t[pre].l&&t[pre].r<=y)return t[pre].val%mod;
spread(pre);
int sum=0;
if(x<=t[pre*2].r)sum=(sum+search(pre*2))%mod;
if(t[pre*2+1].l<=y)sum=(sum+search(pre*2+1))%mod;
return sum;
}
void dfs1(int u,int father){
size[u]=1;
dep[u]=dep[father]+1;
fa[u]=father;
for(int i=0;i<a[u].size();i++){
int v=a[u][i];
if(v==father)continue;
dfs1(v,u);
size[u]+=size[v];
if(size[son[u]]<size[v])son[u]=v;
}
}
void dfs2(int u,int f){
top[u]=f;
x=y=id[u]=++cnt;
wt[cnt]=w[u];
if(!son[u])return;
dfs2(son[u],f);
for(int i=0;i<a[u].size();i++){
int v=a[u][i];
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
}
void uprange(int c,int d){
while(top[c]!=top[d]){
if(dep[c]<dep[d])swap(c,d);
y=id[c],x=id[top[c]];
add(1);
c=fa[top[c]];
}
x=id[c],y=id[d];
if(x>y)swap(x,y);
add(1);
}
int qrange(int c,int d){
int ans=0;
while(top[c]!=top[d]){
if(dep[c]<dep[d])swap(c,d);
y=id[c],x=id[top[c]];
ans=(ans+search(1)%mod)%mod;
c=fa[top[c]];
}
x=id[c],y=id[d];
if(x>y)swap(x,y);
ans=(ans+search(1)%mod)%mod;
return ans;
}
void uptree(int c){
x=id[c],y=id[c]+size[c]-1;
add(1);
}
int qtree(int c){
x=id[c],y=id[c]+size[c]-1;
return search(1)%mod;
}
signed main(){
cin>>n>>m>>root>>mod;
for(int i=1;i<=n;i++){
cin>>w[i];
w[i]%=mod;
}
for(int i=1;i<n;i++){
cin>>x>>y;
a[x].push_back(y);
a[y].push_back(x);
}
dfs1(root,0);
dfs2(root,root);
build(1,n,1);
int flag;
while(m--){
cin>>flag;
int c,d;
if(flag==1){
cin>>c>>d>>k;
k%=mod;
uprange(c,d);
}
else if(flag==2){
cin>>c>>d;
cout<<qrange(c,d)%mod<<"\n";
}
else if(flag==3){
cin>>c>>k;
k%=mod;
uptree(c);
}
else{
cin>>c;
cout<<qtree(c)%mod<<"\n";
}
}
return 0;
}