救救孩子,初学过不了样例

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

BaiBaiShaFeng @ 2024-12-19 19:30:10

#include <bits/stdc++.h>
#define lc k*2
#define rc k*2+1
using namespace std;
int n, m, r, p, cnt=0;
const int MN=1e5+115;
struct EDGE{
    int to, nex, beg, w;
}edge[MN];
void add_node(int x, int y){
    cnt++;
    edge[cnt].to=y;
    edge[cnt].nex=edge[x].beg;
    edge[x].beg=cnt;
    return;
}
struct STN{
    int l, r, val, tag; 
}tr[MN*4];
int wt[MN], w[MN];
int res=0;
int son[MN], id[MN], father[MN], tot, dep[MN], size[MN], top[MN];
void pushup(int k){
    tr[k].val=(tr[lc].val+tr[rc].val)%p;
    return;
}
void build(int k, int l, int r){
    tr[k].l=l; tr[k].r=r;
    if(l==r){
        tr[k].val=wt[l];
        if(tr[k].val>p){tr[k].val%=p;}
        return;
    }
    int mid=(l+r)>>1;
    build(lc,l,mid);build(rc,mid+1,r);
    pushup(k);
    return;
} 
void pushdown(int k){
    if(tr[k].tag){
        tr[lc].tag+=tr[k].tag;
        tr[rc].tag+=tr[k].tag;
        tr[lc].val+=tr[k].tag*(tr[lc].r-tr[lc].l+1);
        tr[rc].val+=tr[k].tag*(tr[rc].r-tr[rc].l+1);
        tr[lc].val%=p;
        tr[rc].val%=p;
        tr[k].tag=0;
    }

}
void update(int k, int l, int r, int v){
    if(tr[k].l>=l&&tr[k].r<=r){
        tr[k].val+=v*(tr[k].r-tr[k].l+1);
        tr[k].tag+=v;
    }else{
        pushdown(k);
        int mid=(tr[k].l+tr[k].r)>>1;
        if(mid>=l){
            update(lc,l,r,v);
        }
        if(mid<r){
            update(rc,l,r,v);
        }
        pushup(k);
    }

}
void query(int k, int l, int r){
    if(tr[k].l>=l&&tr[k].r<=r){
        res+=tr[k].val;
        res%=p;
        return;
    }
    pushdown(k);
    int mid=(tr[k].l+tr[k].r)>>1;
    if(mid>=l){
        query(lc,l,r);
    }
    if(mid<r){
        query(rc,l,r);
    }
}
void dfs1(int x, int f, int depth){
    dep[x]=depth;father[x]=f;size[x]=1;
    int bs=-1;
    for(int i=edge[x].beg;i;i=edge[i].nex){
        int y=edge[i].to;
        if(y==f){
            continue;
        }
        dfs1(y,x,depth+1);
        size[x]+=size[y];
        if(size[y]>bs){
            son[x]=y;
            bs=size[y];
        }
    }
    return;
}
void dfs2(int x, int topf){//我讨厌树链剖分呜呜呜 
    id[x]=++tot;wt[tot]=w[x];top[x]=topf;
    if(!son[x]){
        return;
    }
    dfs2(son[x],topf);
    for(int i=edge[x].beg;i;i=edge[i].nex){
        int y=edge[i].to;
        if(y==father[x]||y==son[x]){
            continue;
        }
        dfs2(y,y);
    }
    return;
}
//难绷的来了 
int Range(int x, int y){
    int ans=0;
    while(top[x]!=top[y]){//两点不同链 
        if(dep[top[x]]<dep[top[y]]){
            swap(x,y);
        }
        res=0;
        query(1,id[top[x]],id[x]);ans+=res;ans%=p;
        x=father[top[x]];//x跳到顶上 

    }
    //马上处就停了 
    if(dep[x]>dep[y]){
        swap(x,y);
    }
    res=0;
    query(1,id[x],id[y]);
    ans+=res;
    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,id[top[x]],id[x],k);
        x=father[top[x]];
    }
    if(dep[x]>dep[y]){
        swap(x,y);
    }
    update(1,id[x],id[y],k);
    return;
}
int Son(int x){
    res=0;
    query(1,id[x],id[x]+size[x]-1);
    return res;
}
void cSon(int x, int k){
    update(1,id[x],id[x]+size[x]-1,k);
    return;
}
int main(){
    scanf("%d%d%d%d",&n,&m,&r,&p);
    for(int i=1; i<=n; i++){scanf("%d",&w[i]);}
    for(int i=1; i<=n; i++){
        int a, b;
        scanf("%d%d",&a,&b);
        add_node(a,b);
        add_node(b,a);
    }
    dfs1(r,0,1);
    dfs2(r,r);
    build(1,1,n);
    for(int i=1; i<=m; i++){
        int op;
        scanf("%d",&op);
        if(op==1){
            int a, b, c;
            scanf("%d%d%d",&a,&b,&c);
            Change(a,b,c);
        }else if(op==2){
            int a, b;
            scanf("%d%d",&a,&b);
            printf("%d\n",Range(a,b));
        }else if(op==3){
            int a, b;
            scanf("%d%d",&a,&b);
            cSon(a,b);
        }else{
            int a;
            scanf("%d",&a);
            printf("%d\n",Son(a));
        }
    }
    return 0;
}

by xpigeon @ 2024-12-19 19:48:25

你小子效率也太高了


by Poole_tea @ 2024-12-19 20:03:36

for(int i=1; i<=n; i++){
        int a, b;
        scanf("%d%d",&a,&b);
        add_node(a,b);
        add_node(b,a);
    }

这不应该是输入n-1条边吗,而且你建图的数组应该开2e5,因为有是无向边@BaiBaiShaFeng


by BaiBaiShaFeng @ 2024-12-19 20:13:05

@Poole_tea 谢谢哦, 一不小心脑残了, 这个连数据都输入不了的代码竟然可以得10分(⊙﹏⊙)


|