每每想要去了解可持久化treap这个好写好调的东东,然后就发现网上只有一个人的——SymenYang的!在此我必须得把他批判一番——写方法不贴代码是什么心态!而且写出来的是有问题的呀!害人不浅!

好吧说正经事,这个版本的treap名叫可持久化treap却没有可持久化,而是借鉴了可持久化treap中的一些写法。貌似可持久化之后反而难写难调。。。在这个版本的treap中加入了堆权值来维护树的形状,然后由三种操作——合并(merge),按size拆分(split_size),按值拆分(split_kth)。先说说merge。merge 这个操作是将两颗子树a,b(b中元素大于等于a中的元素)合并。这是我们这就是一个递归的过程:对于a,b中的当前节点x,y,按照他们的堆权值来确定父亲和儿子的关系,然后再往下递归这个过程,接左儿子还是右儿子看具体的值。然后split中要引入一个nodepair的结构来返回(把一棵拆成两棵得要个结构来返回啊),基本的操作跟在bst上找第k大和前k个的值一致。。具体看代码理解吧。。。 不好画图。。。。

/*
    针对的是平衡二叉树那道入门题
*/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
 
 
const int maxn = 200001;
int ans = 0;
struct node{
    int key,data,size;
    node *son[2];
    node(){ key = rand();}
}e[maxn],*root;int ne = 0;
 
struct nodepair{
    node* l,*r;
};
 
nodepair mkpair(node* a,node* b){
    nodepair x;
    x.l = a, x.r = b;
    return x;
}
 
void update(node* x){
    if(x){//判断不能少!
        x->size = 1;
        if(x->son[0]) x->size += x->son[0]->size;
        if(x->son[1]) x->size += x->son[1]->size;
    }
}
 
node* merge(node* a,node *b){
    if(!a) {update(b);return b;}
    if(!b) {update(a);return a;}
    if(a->key <= b->key){
        a->son[1] = merge(a->son[1],b);
        update(a); return a;
    }
    else{
        b->son[0] = merge(a,b->son[0]);
        update(b); return b;
    }
}
 
nodepair split_size(node* a,int k){
    if(!a) return mkpair(NULL,NULL);
    if(!k) return mkpair(NULL,a);
    int ts = a->son[0] ? a->son[0]->size : 0;
    nodepair km;
    if(ts >= k){
        km = split_size(a->son[0],k);
        a->son[0] = km.r; update(a);
        return mkpair(km.l,a);
    }
    else{
        km = split_size(a->son[1],k - ts - 1);
        a->son[1] = km.l; update(a);
        return mkpair(a,km.r);
    }
}
 
nodepair split_kth(node* a,int k){
    if(!a) return mkpair(NULL,NULL);
    nodepair km;
    if(a->data <= k){
        km = split_kth(a->son[1],k);
        a->son[1] = km.l; update(a);
        return mkpair(a,km.r);
    }
    else{
        km = split_kth(a->son[0],k);
        a->son[0] = km.r; update(a);
        return mkpair(km.l,a);
    }
}
 
node* insert(int v){
    node* now = e + ne++;
    now->data = v;
    nodepair km = split_kth(root,v);
    return merge(km.l,merge(now,km.r));
}
 
node* del(int v){
    nodepair km1 = split_kth(root,v-1);
    nodepair km2 = split_size(km1.r,1);
    return merge(km1.l,km2.r);
}
 
void askkth(int k){
    node* now = root;
    while(true){
        int ts = now->son[0] ? now->son[0]->size : 0;
        if(ts + 1 == k) break;
        else{
            if(ts >= k) now = now->son[0];
            else k -= ts + 1, now = now->son[1];
        }
    }
    ans = now -> data;
}
 
node* askx(int v){
    nodepair km = split_kth(root,v-1);
    ans = km.l ? km.l->size+1 : 1;
    return merge(km.l,km.r);
}
 
node* pre(int v){
    nodepair km1 = split_kth(root,v-1);
    nodepair km2 = split_size(km1.l,km1.l->size - 1);
    ans = km2.r -> data;
    return merge(merge(km2.l,km2.r),km1.r);
}
 
node* sub(int v){
    nodepair km1 = split_kth(root,v);
    nodepair km2 = split_size(km1.r,1);
    ans = km2.l -> data;
    return merge(km1.l,merge(km2.l,km2.r));
}
 
int n;
 
void read(){
    scanf("%d",&n);
    while(n--){
        int tmp,op;
        scanf("%d%d",&tmp,&op);
        if(tmp == 1) root = insert(op);
        if(tmp == 2) root = del(op);
        if(tmp == 3) root = askx(op);
        if(tmp == 4) askkth(op);
        if(tmp == 5) root = pre(op);
        if(tmp == 6) root = sub(op);
        if(tmp == 3 || tmp == 4 || tmp == 5 || tmp == 6) printf("%d\n",ans);
    }
}
 
int main(){
    read();
    return 0;
}