[luogu3369]普通平衡树(fhq-treap模板)

解题关键:无旋treap模板。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define maxn 500001
using namespace std;
typedef long long ll;
int size[maxn],ch[maxn][2],rnd[maxn],val[maxn];
int ncnt,n,x,y,z,rt;

inline void pushup(int x){
    size[x]=1+size[ch[x][0]]+size[ch[x][1]];
}

inline int new_node(int x){
    size[++ncnt]=1;
    val[ncnt]=x;
    rnd[ncnt]=rand();
    return ncnt;
}
//核心
int merge(int A,int B){
    if(!A||!B) return  A+B;
    if(rnd[A]<rnd[B]){ch[A][1]=merge(ch[A][1],B);
        pushup(A);return A;}
    else {ch[B][0]=merge(A,ch[B][0]);
        pushup(B);return B;}
}
//权值分裂
void split(int now,int k,int &x,int &y){
    if(!now) x=y=0;
    else{
        if(val[now]<=k) x=now,split(ch[now][1],k,ch[now][1],y);
        else y=now,split(ch[now][0],k,x,ch[now][0]);
        pushup(now);
    }
}
//排名分裂
void split_2(int now,int k,int &x,int &y){
    if(!now) x=y=0;
    else{
        if(k<=size[ch[now][0]]){y=now;split(ch[now][0],k,x,ch[now][0]);}
        else{x=now;split(ch[now][1],k-size[ch[now][0]]-1,ch[now][1],y);}
        pushup(now);
    }
}

void insert(int &k,int a){
    split(k,a,x,y);
    k=merge(merge(x,new_node(a)),y);
}
//会浪费空间,没有回收节点
void del(int &k,int a){
    split(k,a,x,z);
    split(x,a-1,x,y);
    y=merge(ch[y][0],ch[y][1]);
    k=merge(merge(x,y),z);
}

int rnk(int &k,int a){
    split(k,a-1,x,y);
    int res=size[x]+1;
    k=merge(x,y);
    return res;
}

int kth(int now,int k){
    while(1){
        if(k<=size[ch[now][0]]) now=ch[now][0];
        else if(k==size[ch[now][0]]+1) return val[now];
        else k-=size[ch[now][0]]+1,now=ch[now][1];
    }
}

int pred(int &k,int a){
    split(k,a-1,x,y);
    int res=kth(x,size[x]);
    k=merge(x,y);
    return res;
}

int succ(int &k,int a){
    split(k,a,x,y);
    int res=kth(y,1);
    k=merge(x,y);
    return res;
}

int main(){
    srand(time(0));
    scanf("%d",&n);
    for(int i=1,opt,a;i<=n;i++){
        scanf("%d%d",&opt,&a);
        switch(opt){
            case 1:insert(rt,a);break;
            case 2:del(rt,a);break;
            case 3:printf("%d\n",rnk(rt,a));break;
            case 4:printf("%d\n",kth(rt,a));break;
            case 5:printf("%d\n",pred(rt,a));break;
            case 6:printf("%d\n",succ(rt,a));break;
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/elpsycongroo/p/10371406.html