为什么会RE,只有第11个点 AC

P3384 【模板】重链剖分/树链剖分

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;
}

样例可以过


|