样例输出 10 10
#include<iostream>
using namespace std;
const int N=100100;
inline long long read(){
long long r=0,s=1,i=getchar();
while(i<'0'||i>'9'){if(i=='-')s=-1;i=getchar();}
while(i>='0'&&i<='9')r=(r<<1)+(r<<3)+(i^48),i=getchar();
return s*r;
}
struct segment_tree{
int n,P,L[N<<2],R[N<<2];
long long a[N],sum[N<<2],laz[N<<2];
inline int ls(int i){return i<<1;}
inline int rs(int i){return i<<1|1;}
inline void push_down(int i){
sum[i]=(sum[i]+(R[i]-L[i]+1)*laz[i]%P)%P;
laz[ls(i)]=(laz[ls(i)]+laz[i])%P;laz[rs(i)]=(laz[rs(i)]+laz[i])%P;
laz[i]=0;
}
inline void push_up(int i){
push_down(ls(i)),push_down(rs(i));
sum[i]=(sum[ls(i)]+sum[rs(i)])%P;
}
int build(int id,int l,int r){
L[id]=l,R[id]=r;int mid=(l+r)>>1;
if(l==r){sum[id]=a[l];return a[l];}
return sum[id]=(build(ls(id),l,mid)+build(rs(id),mid+1,r))%P;
}
void add(int id,int l,int r,long long k){
push_down(id);int mid=(L[id]+R[id])>>1;
if(l==L[id]&&r==R[id]){laz[id]=(laz[id]+k)%P;return;}
if(l<=mid)add(ls(id),l,min(mid,r),k);
if(r>mid)add(rs(id),max(l,mid+1),r,k);
push_up(id);
}
long long get(int id,int l,int r){
push_down(id);int mid=(L[id]+R[id])>>1;
if(l==L[id]&&r==R[id]){return sum[id];}
return ((l<=mid?get(ls(id),l,min(mid,r)):0)+(r>mid?get(rs(id),max(l,mid+1),r):0))%P;
}
void init(int n,int p){
P=p;
for(int i=1;i<=n;i++)a[i]=read()%P;
build(1,1,n);
}
}bst;
int n,m,root,p;
int to[N<<2],nex[N<<2],head[N];
int top[N],fa[N],siz[N],dfn[N],redfn[N],hson[N],dis[N],son[N],bro[N],cnt;
int build(int id,int dep){
dis[id]=dep;siz[id]=1;
for(int i=head[id];i;i=nex[i]){
if(dis[to[i]])continue;
bro[to[i]]=son[id];son[id]=to[i];
siz[id]+=build(to[i],dep+1);
fa[to[i]]=id;
if(siz[to[i]]>siz[hson[id]])hson[id]=to[i];
}
return siz[id];
}
void decompose(int id,int tp){
top[id]=tp;dfn[id]=++cnt;redfn[cnt]=id;
if(hson[id]){
decompose(hson[id],tp);
for(int i=son[id];i;i=bro[i])if(i!=hson[id])decompose(i,i);
}
}
void init(){
cin>>n>>m>>root>>p;
bst.init(n,p);
for(int i=1;i<n;i++){
int u=read(),v=read();
to[i<<1]=v;nex[i<<1]=head[u];head[u]=(i<<1);
to[(i<<1)-1]=u;nex[(i<<1)-1]=head[v];head[v]=(i<<1)-1;
}
build(root,1);
decompose(root,root);
}
int main(){
// freopen("C://read.in","r",stdin);
init();
for(int i=1;i<=n;i++)cout<<[i]<<' '<<endl;
while(m--){
int opt=read();
if(opt==1){
int x=read(),y=read(),z=read()%p;
while(top[x]!=top[y]){
if(dis[top[x]]<dis[top[y]])swap(x,y);
bst.add(1,dfn[top[x]],dfn[x],z);
x=fa[top[x]];
}
if(dis[x]>dis[y])swap(x,y);
bst.add(1,dfn[x],dfn[y],z);
}
else if(opt==2){
int x=read(),y=read(),sum=0;
while(top[x]!=top[y]){
if(dis[top[x]]<dis[top[y]])swap(x,y);
sum=(sum+bst.get(1,dfn[top[x]],dfn[x]))%p;
x=fa[top[x]];
}
if(dis[x]>dis[y])swap(x,y);
sum=(sum+bst.get(1,dfn[x],dfn[y]))%p;
printf("%d\n",sum);
}
else if(opt==3){
int x=read(),z=read()%p;
bst.add(1,dfn[x],dfn[x]+siz[x]-1,z);
}
else{
int x=read();
printf("%lld\n",bst.get(1,dfn[x],dfn[x]+siz[x]-1));
}
}
return 0;
}