#include<bits/stdc++.h>
#define N 100005
using namespace std;
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<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
inline void write(int x){
int tmp=x<0?-x:x,cnt=0;char f[200];
if(!x)
putchar('0');
if(x<0)
putchar('-');
while(tmp){
f[cnt++]=tmp%10+'0';
tmp/=10;
}
while(cnt)
putchar(f[--cnt]);
putchar('\n');
}
int n,x,y,flag,z,mod,q,root,tp[N],id[N],t,ans;
int L,R,b[N<<3],tag[N<<3],v[N];
int head[N],nxt[N<<1],to[N],p;
int dep[N],f[N],sz[N],son[N],W[N];
inline void Build(int u,int v){
nxt[++p]=head[u];head[u]=p;to[p]=v;
nxt[++p]=head[v];head[v]=p;to[p]=u;
}
void dfs1(int k,int fa,int deep){
dep[k]=deep++;
f[k]=fa;
sz[k]=1;
for(int i=head[k];i;i=nxt[i])
if(to[i]!=fa){
dfs1(to[i],k,deep);
sz[k]+=sz[to[i]];
if(sz[to[i]]>sz[son[k]])
son[k]=to[i];
}
}
void dfs2(int k,int top){
id[k]=++t;
W[t]=v[k];
tp[k]=top;
if(!son[k])
return;
dfs2(son[k],top);
for(int i=head[k];i;i=nxt[i])
if(to[i]!=f[k]&&to[i]!=son[k])
dfs2(to[i],to[i]);
}
inline int ls(int w){
return w<<1;
}
inline int rs(int w){
return w<<1|1;
}
inline void push_up(int w){
b[w]=(b[ls(w)]+b[rs(w)])%mod;
}
void build(int w,int l,int r){
if(l==r){
b[w]=W[l];
return;
}
int mid=(l+r)>>1;
build(ls(w),l,mid);
build(rs(w),mid+1,r);
push_up(w);
}
inline void push_down(int w,int l,int r){
// cout<<w<<" ";
int mid=(l+r)>>1;
b[ls(w)]=(b[ls(w)]+tag[w]*(mid-l+1)%mod)%mod;
b[rs(w)]=(b[rs(w)]+tag[w]*(r-mid)%mod)%mod;
tag[ls(w)]+=tag[w];
tag[rs(w)]+=tag[w];
tag[w]=0;
}
void query(int w,int l,int r){
if(L<=l&&R>=r){
ans=(ans+b[w])%mod;
return;
}
int mid=(l+r)>>1;
if(tag[w])
push_down(w,l,r);
if(L<=mid)
query(ls(w),l,mid);
if(R>mod)
query(rs(w),mid+1,r);
}
void update(int w,int l,int r){
if(L<=l&&R>=r){
b[w]=(b[w]+(r-l+1)*z%mod)%mod;
tag[w]+=z;
return;
}
int mid=(l+r)>>1;
if(tag[w])
push_down(w,l,r);
if(L<=mid)
update(ls(w),l,mid);
if(R>mid)
update(rs(w),mid+1,r);
push_up(w);
}
void findup(){
while(tp[x]!=tp[y]){
if(dep[tp[x]]<dep[tp[y]])
swap(x,y);
L=id[tp[x]];
R=id[x];
update(1,1,n);
x=f[tp[x]];
}
if(dep[x]>dep[y])
swap(x,y);
L=id[x];
R=id[y];
update(1,1,n);
}
int findqu(){
int res=0;
while(tp[x]!=tp[y]){
if(dep[tp[x]]<dep[tp[y]])
swap(x,y);
L=id[tp[x]];
R=id[x];
ans=0;
query(1,1,n);
res=(res+ans)%mod;
x=f[tp[x]];
}
if(dep[x]>dep[y])
swap(x,y);
L=id[x];
R=id[y];
ans=0;
query(1,1,n);
res=(res+ans)%mod;
return res;
}
int main(){
n=read();q=read();root=read();mod=read();
for(register int i=1;i<=n;i++)
v[i]=read()%mod;
for(int i=1;i<n;i++)
Build(read(),read());
dfs1(root,0,1);
dfs2(root,root);
build(1,1,n);
while(q--){
flag=read();
if(flag==1){
x=read();y=read();z=read()%mod;
findup();
}
if(flag==2){
x=read();y=read();
write(findqu());
}
if(flag==3){
x=read();z=read()%mod;
L=id[x];
R=id[x]+sz[x]-1;
update(1,1,n);
}
if(flag==4){
x=read();
L=id[x];
R=id[x]+sz[x]-1;
ans=0;
query(1,1,n);
write(ans);
}
}
return 0;
}
板子题打了一下午,我还是太蒻了……