treap板子玄关求调

P6136 【模板】普通平衡树(数据加强版)

apple_vinegar @ 2024-11-06 16:05:03

#include<bits/stdc++.h>
#define int long long
#define mid ((l+(r-l)>>1))
#define ls (p<<1)
#define rs (ls|1)
#define lt ls,l,mid
#define rt rs,mid,r
using namespace std;
const int INF=1e15,N=1e5+5;
int last,tot,root,ans;

inline int read(){
    int a=1,b=0;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') a=-a;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        b=(b<<1)+(b<<3)+(ch^48);
        ch=getchar();
    }
    return a*b;
}

struct node{
    int l,r;
    int val,dat;
    int cnt,size;
};
node a[N];

inline int add(int val){
    a[++tot].val=val;
    a[tot].dat=rand();
    a[tot].cnt=a[tot].size+1;
    return tot;
}

inline void update(int p){
    a[p].size=a[a[p].l].size+a[a[p].r].size+a[p].cnt;
}

inline void build(){
    add(-INF),add(INF);
    root=1,a[1].r=2;
    update(root);
}

inline void zig(int &p){//right
    int q=a[p].l;
    a[p].l=a[q].r;
    a[q].r=p;
    p=q;
    update(a[p].r),update(p);
}

inline void zag(int &p){//left
    int q=a[p].r;
    a[p].r=a[q].l;
    a[q].l=p;
    p=q;
    update(a[p].l),update(p);
}

inline void insert(int &p,int val){
    if(p==0){
        p=add(val);
        return;
    }
    if(val==a[p].val){
        a[p].cnt++;
        update(p);
        return ;
    }
    if(val<a[p].val){
        insert(a[p].l,val);
        if(a[p].dat<a[a[p].l].dat){
            zig(p);
        }
    }
    else{
        insert(a[p].r,val);
        if(a[p].dat<a[a[p].r].dat) zag(p);
    }
    update(p);
}

inline void remove(int &p,int val){
    if(p==0) return ;
    if(val==a[p].val){
        if(a[p].cnt>1){
            a[p].cnt--;
            update(p);
            return;
        }
        if(a[p].l||a[p].r){
            if(!a[p].l||a[a[p].l].dat>a[a[p].r].dat){
                zig(p);
                remove(a[p].r,val);
            }
            else{
                zag(p);
                remove(a[p].l,val);
            }
            update(p);
        }
        else p=0;
        return;
    }
    if(val<a[p].val) remove(a[p].l,val);
    else remove(a[p].r,val);
    update(p);
}

inline int findrank(int p,int val){
    if(p==0) return 0;
    if(val==a[p].val) return a[a[p].l].size+1;
    if(val<a[p].val) return findrank(a[p].l,val);
    else return findrank(a[p].r,val)+a[a[p].l].size+a[p].cnt;
}

inline int findwho(int p,int rank){
    if(p==0) return INF;
    if(a[a[p].l].size>=rank) return findwho(a[p].l,rank);
    if(a[a[p].l].size+a[p].cnt>=rank) return a[p].val;
    return findwho(a[p].r,rank-a[a[p].l].size-a[p].cnt);
}

inline int getpre(int val){
    int ans=1;
    int p=root;
    while(p){
        if(val==a[p].val){
            if(a[p].l>0){
                p=a[p].l;
                while(a[p].r>0) p=a[p].r;
                ans=p;
            }
            break;
        }
        if(a[p].val<val&&a[p].val>a[ans].val) ans=p;
        if(val<a[p].val) p=a[p].l;
        else p=a[p].r;
    }
    return a[ans].val;
}

inline int getnext(int val){
    int ans=2;
    int p=root;
    while(p){
        if(val==a[p].val){
            if(a[p].r>0){
                p=a[p].r;
                while(a[p].l>0) p=a[p].l;
                ans=p;
            }
            break;
        }
        if(a[p].val>val&&a[p].val<a[ans].val) ans=p;
        if(val<a[p].val) p=a[p].l;
        else p=a[p].r;
    }
    return a[ans].val;
}

signed main(){
    // freopen("a","w",stdout);
    srand(time(0));
    int n=read(),m=read();

    build();
    for(int i=1;i<=n;i++) insert(root,read());
    while(m--){
        int op=read(),x=read();
        x^=last;
        if(op==1){
            insert(root,x);
        }
        if(op==2){
            remove(root,x);
        }
        if(op==3){
            last=(findrank(root,x)-1);
        }
        if(op==4){
            last=findwho(root,x+1);
        }
        if(op==5){
            last=getpre(x);
        }
        if(op==6){
            last=getnext(x);
        }
        cout<<last<<endl;
        if(op>=3) ans^=last;
        // cout<<last<<endl;
    }
    cout<<ans;
    return 0;
}

by Hagasei @ 2024-11-06 17:07:58

@penggc16801


by Hagasei @ 2024-11-06 17:08:24

然后即可 ac。


by Hagasei @ 2024-11-06 17:12:05

以及 getpre 和 getnext 可以通过 findrank findwho 直接表示的,不用单独写函数。


by apple_vinegar @ 2024-11-06 17:12:20

@Hagasei %%%,可以问一下,第三点为什么已经特判了为叶子节点的情况还要加 a[p].l&& 吗?


by apple_vinegar @ 2024-11-06 17:15:38

等等,唐了,thx


by apple_vinegar @ 2024-11-06 17:20:41

@Hagasei 是用二分找到数再findrank吗?


by Hagasei @ 2024-11-06 17:38:01

@penggc16801 pre(x)=findwho(findrank(x)-1)


by chen_z @ 2024-11-06 17:42:31

@penggc16801 大佬您太巨了%%%


by HourSkit @ 2024-11-06 20:13:43

%%%


上一页 |