rt,马蜂自认为舒服
#include<bits/stdc++.h>
using namespace std;
const int xrt=1e5+3;
int dep[xrt],fa[xrt],son[xrt],size[xrt];
int idx[xrt],rev[xrt],top[xrt];
int n,m,r,p;
int dis[xrt];
int head[xrt];
struct zsm{
int to;
int next;
}e[xrt<<1];
struct Tree{
int l,r;
int sum;
int lazy;
}t[xrt<<2];
int cnt,tot;
void insery(int x,int y){
e[++cnt].to=y;
e[cnt].next=head[x];
head[x]=cnt;
}
void dfs1(int x,int f){
size[x]=1;
for(int i=head[x];i;i=e[i].next){
int t=e[i].to;
if(t==f)continue;
dep[t]=dep[x]+1;
fa[t]=x;
dfs1(t,x);
size[x]+=size[t];
if(size[t]>size[son[x]]){
son[x]=t;
}
}
return;
}
void dfs2(int x,int t){
top[x]=t;
idx[x]=++tot;
rev[tot]=x;
if(!son[x])return;
dfs2(son[x],t);
for(int i=head[x];i;i=e[i].next){
int t=e[i].to;
if(t!=fa[x]&&t!=son[x]){
dfs2(t,t);
}
}
return;
}
void build(int x,int l,int r){
t[x].l=l,t[x].r=r;
if(l==r){
t[x].sum=dis[rev[l]];
return;
}
int mid=l+((r-l)>>1);
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
t[x].sum=t[x<<1].sum+t[x<<1|1].sum;
return;
}
void down(int x){
if(t[x].lazy){
t[x<<1].sum+=(t[x<<1].r-t[x<<1].l+1)*t[x].lazy;
t[x<<1].lazy+=t[x].lazy;
t[x<<1|1].sum+=(t[x<<1|1].r-t[x<<1|1].l+1)*t[x].lazy;
t[x<<1|1].lazy+=t[x].lazy;
t[x].lazy=0;
}
}
void add(int x,int l,int r,int k){
if(t[x].l>=l&&t[x].r<=r){
t[x].sum+=(t[x].r-t[x].l+1)*k;
t[x].lazy+=k;
return;
}
down(x);
int mid=t[x].l+((t[x].r-t[x].l)>>1);
if(l<=mid){
add(x<<1,l,r,k);
}
if(r>mid){
add(x<<1|1,l,r,k);
}
return;
}
int finds(int x,int l,int r){
if(t[x].l>=l&&t[x].r<=r){
return t[x].sum;
}
down(x);
int mid=t[x].l+((t[x].r-t[x].l)>>1);
int ans=0;
if(l<=mid){
ans+=finds(x<<1,l,r);
}
if(r>mid){
ans+=finds(x<<1|1,l,r);
}
return ans;
}
void work1(int x,int y,int z){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]){
swap(x,y);
}
add(1,idx[top[x]],idx[x],z%p);
x=fa[top[x]];
}
if(dep[x]>dep[y]){
swap(x,y);
}
add(1,idx[x],idx[y],z%p);
return;
}
void work2(int x,int y){
int ans=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]){
swap(x,y);
}
ans=(ans+finds(1,idx[top[x]],idx[x]))%p;
x=fa[top[x]];
}
if(dep[x]>dep[y]){
swap(x,y);
}
ans=(ans+finds(1,idx[x],idx[y]))%p;
cout<<ans<<"\n";
return;
}
void work3(int x,int z){
add(1,idx[x],idx[x]+size[x]-1,z%p);
}
void work4(int x){
cout<<finds(1,idx[x],idx[x]+size[x]-1)%p<<"\n";
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m>>r>>p;
for(int i=1;i<=n;i++){
cin>>dis[i];
}
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
insery(u,v);
insery(v,u);
}
dep[r]=1;
dfs1(r,0);
dfs2(r,1);
build(1,1,n);
for(int i=1;i<=m;i++){
int op;
cin>>op;
if(op==1){
int x,y,z;
cin>>x>>y>>z;
work1(x,y,z);
}else if(op==2){
int x,y;
cin>>x>>y;
work2(x,y);
}else if(op==3){
int x,z;
cin>>x>>z;
work3(x,z);
}else if(op==4){
int x;
cin>>x;
work4(x);
}
}
return 0;
}