求助,样例过不了

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

like_tis @ 2023-11-25 20:28:57

#include<bits/stdc++.h>
#define ll long long
#define N 100005
using namespace std;
int n,T,r,p,vis;
int dep[N],Size[N],wc[N],fa[N],top[N],rdfn[N],dfn[N];
vector<int> tree[N];
ll a[N];
//dfn:树编号-->链编号
//rdfn:链编号-->树编号
namespace seg{
    ll w[N*4]={0},tag[N*4]={0};
    void pushup(int u){
        w[u]=(w[u*2]+w[u*2+1])%p;
    }
    void maketag(int u,int len,ll v){
        tag[u]+=v;
        w[u]+=len*v%p;
        tag[u]%=p;
        w[u]%=p;
    }
    void pushdown(int u,int l,int r){
        int mid=(l+r)/2;
        maketag(u*2,mid-l+1,tag[u]);
        maketag(u*2+1,r-mid,tag[u]);
        tag[u]=0;
    }
    bool inRange(int l,int r,int L,int R){
        return(L<=l&&r<=R);
    }
    bool outOfRange(int l,int r,int L,int R){
        return(l>R||r<L);
    }
    void build(int u,int l,int r){
        if(l==r){
            w[u]=a[rdfn[u]]%p;
            return;
        }
        int mid=(l+r)/2;
        build(u*2,l,mid);
        build(u*2+1,mid+1,r);
        pushup(u);
    }
    ll query(int u,int l,int r,int L,int R){
        if(inRange(l,r,L,R)) return w[u]%p;
        else if(!outOfRange(l,r,L,R)){
            int mid=(l+r)/2;
            pushdown(u,l,r);
            return (query(u*2,l,mid,L,R)+query(u*2+1,mid+1,r,L,R))%p;
        }
        else return 0;
    }
    void update(int u,int l,int r,int L,int R,ll v){
        if(inRange(l,r,L,R)) maketag(u,r-l+1,v);
        else if(!outOfRange(l,r,L,R)){
            int mid=(l+r)/2;
            pushdown(u,l,r);
            update(u*2,l,mid,L,R,v);
            update(u*2+1,mid+1,r,L,R,v);
            pushup(u);
        }
    }
}
void dfs1(int u,int from){
    dep[u]=dep[from]+1;
    Size[u]=1;
    fa[u]=from;
    for(auto v:tree[u])if(v!=from){
        dfs1(v,u);
        Size[u]+=Size[v];
        if(Size[v]>Size[wc[u]]) wc[u]=v;
    }
}
void dfs2(int u,int Top){
    dfn[u]=++vis;
    rdfn[vis]=u;
    top[u]=Top;
    if(wc[u]!=0){
        dfs2(wc[u],Top);
        for(auto v:tree[u])if(v!=fa[u]&&v!=wc[u]){
            dfs2(v,v);
        }
    }
}
ll qry(int x,int y){
    ll ans=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans+=seg::query(1,1,n,dfn[top[x]],dfn[x]);
        ans%=p;
        x=fa[top[x]];
    }
    ans+=seg::query(1,1,n,min(dfn[x],dfn[y]),max(dfn[x],dfn[y]));
    ans%=p;
    return ans;
}
void upd(int x,int y,ll v){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        seg::update(1,1,n,dfn[top[x]],dfn[x],v);
        x=fa[top[x]];
    }
    seg::update(1,1,n,min(dfn[x],dfn[y]),max(dfn[x],dfn[y]),v);
}
int main(){
    scanf("%d%d%d%d",&n,&T,&r,&p);
    for(int i=1;i<=n;i++) scanf("%lld",a+i);
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        tree[u].push_back(v);
        tree[v].push_back(u);
    }
    dfs1(r,0);
    dfs2(r,0);
    seg::build(1,1,n);
    while(T--){
        int op,x,y,z;
        scanf("%d",&op);
        if(op==1){
            scanf("%d%d%d",&x,&y,&z);
            upd(x,y,z);
        }
        else if(op==2){
            scanf("%d%d",&x,&y);
            printf("%lld\n",qry(x,y));
        }
        else if(op==3){
            scanf("%d%d",&x,&z);
            seg::update(1,1,n,dfn[x],dfn[x]+Size[x]-1,z);
        }
        else{
            scanf("%d",&x);
            printf("%lld\n",seg::query(1,1,n,dfn[x],dfn[x]+Size[x]-1));
        }
    }
    return 0;
}

by like_tis @ 2023-11-25 20:35:07

发现了一个dfs2(r,0);应该写成dfs2(r,r);

但还是错的


by lixiaze1234567 @ 2023-11-25 20:36:07

能过的了我把你吃了


by like_tis @ 2023-11-25 20:39:56

@lixiaze1234567

你什么意思


by lixiaze1234567 @ 2023-11-26 10:31:33

我没看到你上一条发的


by like_tis @ 2023-11-26 12:09:48

此贴结

build中的w[u]=a[rdfn[u]]%p;

应写为w[u]=a[rdfn[l]]%p;

警示后人


by Jorisy @ 2024-04-14 16:14:10

@like_tis_yzx 谢谢你,我也是错的这个 /tuu


|