#include<bits/stdc++.h>
using namespace std;
#define int long long
const int nn=1e6+5;
int n,m,r,p,head[nn],nxt[nn*2],f[nn],d[nn],sz[nn],son[nn],cnt;
int rk[nn],a[nn],mod,top[nn],id[nn];
struct node{
int u,v;
}edge[nn*2];
struct student{
int l,r,lazy,sum;
}tree[nn*4];
inline void build(int l,int r,int o){
tree[o].l=l,tree[o].r=r;
if(l==r){
tree[o].sum=a[rk[l]];
return ;
}
int mid=(l+r)>>1;
build(l,mid,o*2),build(mid+1,r,o*2+1);
tree[o].sum=(tree[o*2].sum+tree[o*2+1].sum)%p;
}
inline void biao(int o){
tree[o*2].sum+=tree[o].lazy*(tree[o*2].r-tree[o*2].l+1)%mod;
tree[o*2].sum%=mod;
tree[o*2+1].sum+=tree[o].lazy*(tree[o*2+1].r-tree[o*2+1].l+1)%mod;
tree[o*2+1].sum%=mod;
tree[o*2].lazy=(tree[o*2].lazy+tree[o].lazy)%mod;
tree[o*2+1].lazy=(tree[o*2+1].lazy+tree[o].lazy)%mod;
tree[o].lazy=0;
}
inline void update(int l,int r,int c,int o){
if(tree[o].l==l&&tree[o].r==r){
tree[o].sum+=(r-l+1)*c%p;
tree[o].sum%=p;
tree[o].lazy+=c;
tree[o].lazy%=p;
return ;
}
biao(o);
int mid=(tree[o].l+tree[o].r)>>1;
if(l<=mid) update(l,min(r,mid),c,o*2);
if(mid<r) update(max(l,mid+1),r,c,o*2+1);
tree[o].sum=(tree[o*2].sum+tree[o*2+1].sum)%p;
}
inline int query(int l,int r,int o){
if(tree[o].l==l&&tree[o].r==r) return tree[o].sum;
biao(o);
int ans=0;
int mid=(tree[o].l+tree[o].r)>>1;
if(l<=mid) ans=(ans+query(l,min(r,mid),o*2))%mod;
if(mid<r) ans=(ans+query(max(l,mid+1),r,o*2+1))%mod;
return ans;
}
inline void add(int u,int v){
cnt++;
edge[cnt].u=u,edge[cnt].v=v;
nxt[cnt]=head[u];
head[u]=cnt;
}
inline void dfs1(int u,int fa,int depth){
f[u]=fa;
d[u]=depth;
sz[u]=1;
for(int i=head[u];i;i=nxt[i]){
int v=edge[i].v;
if(v==fa) continue;
dfs1(v,u,depth+1);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]]) son[u]=v;
}
}
inline void dfs2(int u,int t){
top[u]=u;
cnt++,id[u]=cnt;
rk[cnt]=u;
if(!son[u]) return ;
dfs2(son[u],t);
for(int i=head[u];i;i=nxt[i]){
int v=edge[i].v;
if(v!=son[u]&&v!=f[u]) dfs2(v,v);
}
}
inline void updates(int x,int y,int c){
int fx=top[x],fy=top[y];
while(fx!=fy){
if(d[fx]>=d[fy]){
update(id[fx],id[x],c,1);
x=f[fx],fx=top[x];
}
else{
update(id[fy],id[y],c,1);
y=f[fy],fy=top[y];
}
}
if(id[x]<=id[y]) update(id[x],id[y],c,1);
else update(id[y],id[x],c,1);
}
inline int sum(int x,int y){
int ans=0;
int fx=top[x],fy=top[y];
while(fx!=fy){
if(d[fx]>=d[fy]){
ans=(ans+query(id[fx],id[x],1))%mod;
x=f[fx],fx=top[x];
}
else{
ans=(ans+query(id[fy],id[y],1))%mod;
y=f[fy],fy=top[y];
}
}
if(id[x]<=id[y]) ans=(ans+query(id[x],id[y],1));
else ans=(ans+query(id[y],id[x],1));
return ans%p;
}
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
void write(int x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
return;
}
signed main(){
std::ios::sync_with_stdio(false),std::cin.tie(nullptr);
n=read(),m=read(),r=read(),p=read();
mod=p;
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<n;i++){
int u,v;u=read(),v=read();
add(u,v),add(v,u);
}
cnt=0;
dfs1(r,0,1),dfs2(r,r);
build(1,n,1);
for(int i=1;i<=m;i++){
int op,x,y,z;
op=read();
if(op==1){
x=read(),y=read(),z=read();
updates(x,y,z);
}
else if(op==2){
x=read(),y=read();
write(sum(x,y)),putchar('\n');
}
else if(op==3){
x=read(),z=read();
update(id[x],id[x]+sz[x]-1,z,1);
}
else{
x=read();
write(query(id[x],id[x]+sz[x]-1,1)),putchar('\n');
}
}
return 0;
}
TLE+WA