#include<bits/stdc++.h>
using namespace std;
#define long long int;
int mod,d[500005],size[500005],fa[500005],z[500005],n,m,cnt,r,p,w[500005],top[500005],id[500005],nw[500005],lll;
vector<int> tree[500005];
struct data {
int l;
int r;
int sum;
int lazy;
} t[2000005];
void dfs1(int now,int f) {
size[now]=1;
fa[now]=f;
for(int i=0; i<tree[now].size(); i++) {
int to=tree[now][i];
if(to==f) continue;
fa[to]=now;
d[to]=d[now]+1;
dfs1(to,now);
size[now]+=size[to];
z[now]=((size[to]>size[z[now]]) ? to : z[now]);
}
}
void dfs2(int now) {
id[now]=++cnt;
nw[cnt]=w[now];
top[now]=(z[fa[now]]==now) ? top[fa[now]] : now;
if(!z[now])
return;
dfs2(z[now]);
for(int i=0; i<tree[now].size(); i++) {
int to=tree[now][i];
if(to!=fa[now]&&to!=z[now]&&fa[to]!=0)
dfs2(to);
}
}
void build(int p,int l,int r) {
t[p].l=l;
t[p].r=r;
if(l==r)
t[p].sum=nw[l]%mod;
else {
int mid=(l+r)>>1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
t[p].sum=t[p*2].sum+t[p*2+1].sum;
t[p].sum%=mod;
}
return;
}
void add(int l,int r,int num,int p) {
if(t[p].l>=l&&t[p].r<=r) {
t[p].sum+=(t[p].r-t[p].l+1)*num;
t[p].lazy+=num;
t[p].sum%=mod;
t[p].lazy%=mod;
return;
} else if(t[p].l>r||t[p].r<l)
return;
else
t[p].sum+=(min(t[p].r,r)-max(t[p].l,l)+1)*num;
if(t[p*2].r>=l)
add(l,r,num,p*2);
if(t[p*2+1].l<=r)
add(l,r,num,p*2+1);
}
int query(int l,int r,int p) {
int ans=0;
if(t[p].l>=l&&t[p].r<=r) {
ans+=t[p].sum;
ans%=mod;
return ans;
} else if(t[p].l>r||t[p].r<l)
return ans;
else
ans=(ans+(min(t[p].r,r)-max(t[p].l,l)+1)*t[p].lazy)%mod;
if(t[p*2].r>=l)
ans=(ans+query(l,r,p*2))%mod;
if(t[p*2+1].l<=r)
ans=(ans+query(l,r,p*2+1))%mod;
return ans%mod;
}
void lca_add(int u,int v,int z) {
while(top[u]!=top[v]) {
if(d[top[u]]<d[top[v]])
swap(u,v);
add(id[top[u]],id[u],z%mod,1);
u=fa[top[u]];
}
if(d[u]>d[v])
swap(u,v);
add(id[u],id[v],z%mod,1);
return;
}
int lca_query(int u,int v) {
int ans=0;
while(top[u]!=top[v]) {
if(d[top[u]]<d[top[v]])
swap(u,v);
ans=(ans+query(id[top[u]],id[u],1))%mod;
u=fa[top[u]];
}
if(d[u]>d[v])
swap(u,v);
ans=(ans+query(id[u],id[v],1))%mod;
return ans%mod;
}
signed main() {
cin>>n>>m>>r>>mod;
for(int i=1; i<=n; i++)
cin>>w[i];
for(int i=1; i<n; i++) {
int u,v;
cin>>u>>v;
tree[u].push_back(v);
tree[v].push_back(u);
}
dfs1(r,0);
dfs2(r);
fa[r]=0;
build(1,1,n);
while(m--) {
int op,x,y,z;
cin>>op;
if(op==1) {
cin>>x>>y>>z;
lca_add(x,y,z%mod);
}
if(op==2) {
cin>>x>>y;
cout<<lca_query(x,y)%mod<<'\n';
}
if(op==3) {
cin>>x>>z;
add(id[x],id[x]+size[x]-1,z%mod,1);
}
if(op==4) {
cin>>x;
cout<<query(id[x],id[x]+size[x]-1,1)%mod<<'\n';
}
}
return 0;
}