树链剖分 19分求调

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

_wsq_ @ 2023-11-07 16:47:18

代码里估计有一堆奇奇怪怪的 bug,调了几周调不出来

#include <iostream>
using namespace std;
#define maxn 100005
typedef long long ll;
int n,m,r,p,fa[maxn],deep[maxn],size[maxn],hson[maxn],top[maxn],dfn[maxn],rnk[maxn],d[maxn],tot,cnt;
ll a[maxn],num[maxn*2-1],lazy[maxn*2-1];
struct edge{
    int to,next;
}e[maxn*2];
void addedge(int u,int v){
    e[++tot].to=v;
    e[tot].next=d[u];
    d[u]=tot;
}
void dfs1(int x){
    size[x]=1;
    for(int i=d[x];i;i=e[i].next){
        if(e[i].to!=fa[x]){
            fa[e[i].to]=x;
            deep[e[i].to]=deep[x]+1;
            dfs1(e[i].to);
            size[x]+=size[e[i].to];
            if(!hson[x]||size[e[i].to]>size[hson[x]]){
                hson[x]=e[i].to;
            }
        }
    }
}
void dfs2(int x,int t){
    top[x]=t;
    dfn[x]=++cnt;
    rnk[cnt]=x;
    if(!hson[x]){
        return;
    }
    dfs2(hson[x],t);
    for(int i=d[x];i;i=e[i].next){
        if(e[i].to!=hson[x]&&e[i].to!=fa[x]){
            dfs2(e[i].to,e[i].to);
        }
    }
}
void build(int l,int r,int root){
    if(l==r){
        num[root]=a[rnk[l]];
        return;
    }
    int mid=(l+r)/2;
    build(l,mid,root*2);
    build(mid+1,r,root*2+1);
    num[root]=num[root*2]+num[root*2+1];
}
void pushdown(int l,int r,int root){
    int mid=(l+r)/2;
    num[root*2]+=(mid-l+1)*lazy[root];
    lazy[root*2]+=lazy[root];
    num[root*2+1]+=(r-mid)*lazy[root];
    lazy[root*2+1]+=lazy[root];
    lazy[root]=0;
}
void add(int x,int y,int k,int l,int r,int root){
    if(l>=x&&r<=y){
        num[root]+=(r-l+1)*k;
        lazy[root]+=k;
        return;
    }
    if(lazy[root]&&l!=r){
        pushdown(l,r,root);
    }
    int mid=(l+r)/2;
    if(mid>=x){
        add(x,y,k,l,mid,root*2);
    }
    if(mid<y){
        add(x,y,k,mid+1,r,root*2+1);
    }
    num[root]=num[root*2]+num[root*2+1];
}
ll get(int x,int y,int l,int r,int root){
    if(l>=x&&r<=y){
        return num[root];
    }
    if(lazy[root]&&l!=r){
        pushdown(l,r,root);
    }
    int mid=(l+r)/2;
    ll sum=0;
    if(mid>=x){
        sum+=get(x,y,l,mid,root*2);
    }
    if(mid<y){
        sum+=get(x,y,mid+1,r,root*2+1);
    }
    return sum;
}
int main(){
    cin>>n>>m>>r>>p;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        addedge(u,v);
        addedge(v,u);
    }
    dfs1(r);
    dfs2(r,r);
    build(1,n,1);
    for(int i=1;i<=m;i++){
        int op;
        cin>>op;
        switch(op){
            case 1:{
                int x,y;
                ll z;
                cin>>x>>y>>z;
                while(top[x]!=top[y]){
                    if(deep[top[x]]<deep[top[y]]){
                        swap(x,y);
                    }
                    add(dfn[top[x]],dfn[x],z,1,n,1);
                    x=fa[top[x]];
                }
                if(deep[top[x]]<deep[top[y]]){
                    swap(x,y);
                }
                add(dfn[y],dfn[x],z,1,n,1);
                break;
            }
            case 2:{
                int x,y;
                ll ans=0;
                cin>>x>>y;
                while(top[x]!=top[y]){
                    if(deep[top[x]]<deep[top[y]]){
                        swap(x,y);
                    }
                    ans+=get(dfn[top[x]],dfn[x],1,n,1);
                    x=fa[top[x]];
                }
                if(deep[top[x]]<deep[top[y]]){
                    swap(x,y);
                }
                ans+=get(dfn[y],dfn[x],1,n,1);
                cout<<ans%p<<endl;
                break;
            }
            case 3:{
                int x;
                ll z;
                cin>>x>>z;
                add(dfn[x],dfn[x]+size[x]-1,z,1,n,1);
                break;
            }
            case 4:{
                int x;
                cin>>x;
                cout<<get(dfn[x],dfn[x]+size[x]-1,1,n,1)%p<<endl;
            }
        }
    }
    return 0;
}

by _wsq_ @ 2023-11-07 16:57:35

声明一下,我知道我取模不够,但是我第一个点就没过,第一个点不需要取模


by __Chx__ @ 2023-11-08 07:39:52

@54Tiger

125和142行应将

deep[top[x]]<deep[top[y]]

改为

deep[x]<deep[y]

因为两点已经跳到了同一条链上,他们的 top 是相等的,应直接比较两点深度


by _wsq_ @ 2023-11-08 19:32:47

@Chx 非常感谢!!!


|