sszxyyds @ 2024-03-25 09:11:30
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,r,p;
int to[200009],nxt[200009],hd[200009],w[200009],nw[200009];
int a[200009<<2],laz[200009<<2];
int son[200009],id[200009],fa[200009],dep[200009],siz[200009],top[200009];
int sum=0,cnt,cnt2;
void add(int x,int y){
to[++cnt2]=y;
nxt[cnt2]=hd[x];
hd[x]=cnt2;
}
void build(int rt,int l,int r){
if(l==r){
a[rt]=nw[l];
a[rt]%=p;
return;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
a[rt]=(a[rt<<1]+a[rt<<1|1])%p;
}
void pushdown(int rt,int len){
laz[rt<<1]+=laz[rt];
laz[rt<<1|1]+=laz[rt];
a[rt<<1]+=(len-(len>>1))*laz[rt];
a[rt<<1|1]+=(len>>1)*laz[rt];
a[rt<<1]%=p;a[rt<<1|1]%=p;
laz[rt]=0;//important
}
void query(int rt,int l,int r,int x,int y){
if(x<=l&&y>=r){
sum+=a[rt];
sum%=p;
return ;
}
else{
if(laz[rt]){
pushdown(rt,r-l+1);
}
int mid=(l+r)>>1;
if(x<=mid){
query(rt<<1,l,mid,x,y);
}//左区间是否被涉及
if(y>mid){
query(rt<<1|1,mid+1,r,x,y);
}
}
}
void update(int rt,int l,int r,int x,int y,int k){
if(x<=l&&y>=r){
laz[rt]+=k;
a[rt]+=(r-l+1)*k;
}else{
if(laz[rt]){
pushdown(rt,r-l+1);
}
int mid=(l+r)>>1;
if(x<=mid){
update(rt<<1,l,mid,x,y,k);
}//左区间是否被涉及
if(y>mid){
update(rt<<1|1,mid+1,r,x,y,k);
}
a[rt]=(a[rt<<1]+a[rt<<1|1])%p;//每个被访问结点都要更新
}
}
int range(int x,int y){
int ans=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]){
swap(x,y);
}//选深度更深的调整
sum=0;
query(1,1,n,id[top[x]],id[x]);
ans+=sum;ans%=p;
x=fa[top[x]];
}
if(dep[x]>dep[y]){
swap(x,y);
}
sum=0;
query(1,1,n,id[x],id[y]);
ans+=sum;
return ans%p;
}
void change(int x,int y,int k){
k%=p;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]){
swap(x,y);
}
update(1,1,n,id[top[x]],id[x],k);
x=fa[top[x]];
}
if(dep[x]>dep[y]){
swap(x,y);
}
update(1,1,n,id[x],id[y],k);
}
int qson(int x){
sum=0;
query(1,1,n,id[x],id[x]+siz[x]-1);
return sum;
}
int upson(int x,int k){
update(1,1,n,id[x],id[x]+siz[x]-1,k);
}
void dfs1(int x,int f,int deep){
dep[x]=deep;
fa[x]=f;
siz[x]=1;
int mson=-1;
for(int i=hd[x];i;i=nxt[i]){
int y=to[i];
if(y==f){
continue;
}
dfs1(y,x,deep+1);
siz[x]+=siz[y];
if(siz[y]>mson){
son[x]=y;
mson=siz[y];
}
}
}
void dfs2(int x,int topf){
id[x]=++cnt;
nw[cnt]=w[x];//x是当前节点
top[x]=topf;
if(!son[x]){
return ;
}
dfs2(son[x],topf);
for(int i=hd[x];i;i=nxt[i]){
int y=to[i];
if(y==fa[x]||y==son[x]){
continue;
}
dfs2(y,y);
//每个轻儿子就是 新链的顶点
}
}
signed main(){
scanf("%lld%lld%lld%lld",&n,&m,&r,&p);
for(int i=1;i<=n;i++){
scanf("%lld",&w[i]);
}
for(int i=1;i<n;i++){
int a,b;
scanf("%lld%lld",&a,&b);
add(a,b);add(b,a);
}
dfs1(r,0,1);
dfs2(r,r);
build(1,1,n);
while(m--){
int x,y,z,op;
scanf("%lld",&op);
if(op==1){
scanf("%lld%lld%lld",&x,&y,&z);
change(x,y,z);
}
else if(op==2){
scanf("%lld%lld",&x,&y);
printf("%lld\n",range(x,y));
}
else if(op==3){
scanf("%lld%lld",&x,&y);
upson(x,y);
}else{
scanf("%lld",&x);
printf("%lld\n",qson(x));
}
}
return 0;
}
样例可以过