Treap=Tree+Heap
Treap是 排序树 与 堆 的结合。
是一个二叉排序树。
(即对于每一个点,其左子树所有的值小于它,右子树所有的值大于它)
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
#define INF 0x3FFFFFFF
#define MAXN 500000
#define MOD 1000037
struct node{
int key,fix,cnt,siz;
node *ch[2];
}tree[MAXN+5];
/*
key:当前节点的值
fix:优先级
cnt:该节点值重复个数
siz:子孙个数
ch:左右子树的指针
*/
node *root,*NIL,*ncnt;
//root:根 NIL:空 ncnt:总结点个数
void Init(){
NIL=&tree[0];
NIL->ch[0]=NIL->ch[1]=NIL;
NIL->key=-INF,NIL->fix=INF;
NIL->cnt=NIL->siz=0;
ncnt=&tree[1];
root=NIL;
}//初始化
inline node * NewNode(int val){
node *p=++ncnt;
p->key=val,p->fix=rand()%MOD;
p->cnt=p->siz=1;
p->ch[0]=p->ch[1]=NIL;
return p;
}//开拓新一个节点
void PushUp(node *x){
x->siz=x->ch[0]->siz+x->ch[1]->siz+x->cnt;
}//递左右子孙的个数
void Rotate(node *&x,int d){
node *y=x->ch[!d];
x->ch[!d]=y->ch[d];
y->ch[d]=x;
x=y;
PushUp(x->ch[d]);
PushUp(x);
}//旋转
void Insert(node *&rt,int val){
if(rt==NIL){
rt=NewNode(val);
return ;
}
if(rt->key==val){
rt->cnt++,rt->siz++;
return ;
}
int d=val>=rt->key;
Insert(rt->ch[d],val);
if(rt->ch[d]->fix<rt->fix)
Rotate(rt,!d);
PushUp(rt);
}//插入
void Delete(node *&rt,int val){
if(rt->ch[0]==NIL&&rt->ch[1]==NIL){
if(rt->key==val){
rt->cnt--,rt->siz--;
if(rt->cnt==0)rt=NIL;
}
return ;
}
if(rt->key==val)
if(rt->cnt>1){
rt->cnt--,rt->siz--;
return ;
}
else{
int d=rt->ch[0]->fix<rt->ch[1]->fix;
Rotate(rt,d);
Delete(rt->ch[d],val);
}
else{
int d=val>rt->key;
Delete(rt->ch[d],val);
}
PushUp(rt);
}//删除
int GetRank(node* rt,int val){
if(rt==NIL)return 1;
if(val==rt->key)return rt->ch[0]->siz+1;
if(val<rt->key)
return GetRank(rt->ch[0],val);
else
return GetRank(rt->ch[1],val)+rt->ch[0]->siz+rt->cnt;
}//查找该值在当前树中值排第几(从小到大)
node *Select(node *rt,int k){
if(rt==NIL)return NIL;
if(rt->ch[0]->siz>=k)return
Select(rt->ch[0],k);
if(rt->ch[0]->siz+rt->cnt>=k)
return rt;
return Select(rt->ch[1],k-rt->ch[0]->siz-rt->cnt);
}//查找排第几的数(从小到大)
node *FindPrev(int val){
int k=GetRank(root,val);
node *p=Select(root,k-1);
return p;
}//找前驱
node *FindNext(int val){
int k=GetRank(root,val+1);
node *p=Select(root,k);
return p;
}//找后继
int main(){
int n,x,op,k;
node*p;
Init();
scanf("%d",&n);
while(n-->0){
scanf("%d%d",&op,&x);
switch(op){
case 1:
Insert(root,x);break;
case 2:
Delete(root,x);break;
case 3:
k=GetRank(root,x);
printf("%d\n",k);break;
case 4:
p=Select(root,x);
printf("%d\n",p->key);break;
case 5:
p=FindPrev(x);
printf("%d\n",p->key);break;
case 6:
p=FindNext(x);
printf("%d\n",p->key);break;
}
}
}