蒟蒻求助

P3391 【模板】文艺平衡树

Richard21477 @ 2020-07-17 09:49:30

#include<bits/stdc++.h>
using namespace std;
struct node{
    int l;
    int r;
    int num;
    int key;
    int s;
    bool laz;
};
node all[100000];
int root;
int cnt=0;
int nes(int x){//return loc
    all[++cnt].s=1;
    all[cnt].num=x;
    all[cnt].key=rand();
    all[cnt].laz=false;
    return cnt;
}
void done(int loc){
    if (all[loc].laz){
        all[loc].laz=false;
        all[all[loc].l].laz=!all[all[loc].l].laz;
        all[all[loc].r].laz=!all[all[loc].r].laz;
    }
    return;
}
void update(int loc){
    all[loc].s=all[all[loc].l].s+all[all[loc].r].s+1;
    return;
}
/*void split(int loc,int val,int &x,int &y){//from <=val;x->l's r;y->r's l;also root
    if (loc==0){
        x=y=0;
        return;
    }
    if (val>=all[loc].num){
        x=loc;
        split(all[loc].r,val,all[loc].r,y);
    }
    else{
        y=loc;
        split(all[loc].l,val,x,all[loc].l);
    }
    update(loc);
}*/
void split(int loc,int sze,int &x,int &y){
    if (loc==0){
        x=y=0;
        return;
    }
    done(loc);
    if (all[all[loc].l].s>=sze){
        y=loc;
        split(all[loc].l,sze,x,all[loc].l);
    }
    else{
        x=loc;
        split(all[loc].r,sze,all[loc].r,y);
    }
    update(loc);
}
int merge(int le,int ri){//le << ri,return root
    if (le==0||ri==0)
        return le+ri;//l or r
    done(le);
    done(ri);
    if (all[le].key<=all[ri].key){
        all[ri].l=merge(le,all[ri].l);
        update(ri);
        return ri;
    }
    else{
        all[le].r=merge(all[le].r,ri);
        update(le);
        return le;
    }
}
int x,y,z;
int opp[100001];
int ins(int ll,int rr){
    if (ll>rr){
        return 0;
    }
    int mid=(ll+rr)>>1;
    int ro1=nes(mid);
    all[ro1].l=ins(ll,mid-1);
    all[ro1].r=ins(mid+1,rr);
    return ro1;
}
void rev(int l,int r){
    split(root,r,x,z);
    split(root,l-1,x,y);
    all[y].laz=!all[y].laz;
    root=merge(merge(x,y),z);
    return;
}
void print(int loc){
    if (loc==0)
        return;
    done(loc);
    print(all[loc].l);
    printf("%d ",all[loc].num);
    print(all[loc].r);
    return;
}
/*void ins(int val){
    split(root,val,x,y);
    root=merge(merge(x,nes(val)),y);
}
void del(int val){
    split(root,val,x,z);
    split(x,val-1,x,y);//y->val 
    y=merge(all[y].l,all[y].r);
    root=merge(merge(x,y),z);
    return;
}
int askrank(int val){
    split(root,val-1,x,y);
    int ret=all[x].s+1;
    root=merge(x,y);
    return ret;
}
int asknum(int rk){
    int f=root;
    while (f!=0){
        if (all[all[f].l].s+1==rk)
            break;
        if (all[all[f].l].s+1>rk)
            f=all[f].l;
        else{
            rk-=all[all[f].l].s+1;
            f=all[f].r;
        }
    }
    return all[f].num;
}
int bef(int val){
    split(root,val-1,x,y);
    int f=x;
    while (all[f].r!=0){
        f=all[f].r;
    }
    int ret=all[f].num;
    root=merge(x,y);
    return ret;
}
int aft(int val){
    split(root,val,x,y);
    int f=y;
    while (all[f].l!=0){
        f=all[f].l;
    }
    int ret=all[f].num;
    root=merge(x,y);
    return ret;
}*/
int main(){
    srand(time(0));
    int n,m;
    cin>>n>>m;
    root=ins(1,n);
    for (int i=0;i<m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        rev(a,b);
    }
    print(root);
    return 0;
}

by Hauynite @ 2020-07-17 10:04:18

@Richard21477

  1. split中,split(all[loc].r,sze,all[loc].r,y);改为split(all[loc].r,sze-all[all[loc].l].s-1,all[loc].r,y);。这里的sze是相对当前的loc而言的,包括了loc的左子树大小和本身节点的1,向右递归时要减掉。

  2. doneall[loc].laz=false;后面加一句swap(all[loc].l,all[loc].r);,交换左右儿子才能起到翻转作用

  3. ins函数return ro1;前需要update(ro1);

  4. rev函数中第二行split改为split(x,l-1,x,y);。此时根已经分裂掉了,不能再用,应在包含l的x内分裂。


|