使用treap来写的,key是二叉树,val是堆的权重。 我在初始化时候插入了-∞和∞两个节点,但是最后排名的时候有把排名减一或者加一。还是不知道哪里有问题。
#include<bits/stdc++.h>
using namespace std;
const int N=10010;
const int INF=2147483647;
int t,root,idx;
//heap为大根堆
struct node
{
int l,r;
int key,val; //bst的键值,heap的值
int size;
}tr[N];
void pushup(int p) //更新父节点
{
tr[p].size=tr[tr[p].l].size+tr[tr[p].r].size+1;
}
int get_node(int key) //获取新节点
{
tr[++idx].key=key;
tr[idx].val=rand();
tr[idx].size=1;
return idx;
}
void build() //创建正无穷负无穷节点
{
get_node(-INF);
get_node(INF);
root=1,tr[root].r=2; //1为-INF,2为INF
}
void zig(int &p)
{
int q=tr[p].l;
tr[p].l=tr[q].r;
tr[q].r=p;
p=q;
pushup(tr[p].r), pushup(p);
}
void zag(int &p)
{
int q=tr[p].r;
tr[p].r=tr[q].l;
tr[q].l=p;
p=q;
pushup(tr[p].l), pushup(p);
}
void insert(int &p,int key)
{
if(!p) p=get_node(key);
else if(tr[p].key>key)
{
insert(tr[p].l,key);
if(tr[tr[p].l].val>tr[p].val) //左子树堆权值大于父节点,右旋
zig(p);
}
else
{
insert(tr[p].r,key);
if(tr[tr[p].r].val>tr[p].val) //右子树堆权值大于父节点,左旋
zag(p);
}
pushup(p);
}
void remove(int &p,int key)
{
if(!p) return;
if(tr[p].key==key) //找到key
{
if(tr[p].l||tr[p].r)
{
if(!tr[p].r||tr[tr[p].l].val>tr[p].val) //右子树空或者左子树val>根节点
{
zig(p);
remove(tr[p].r,key);
}
else //if(!tr[p].l||tr[tr[p].r].val>tr[p].val)
{
zag(p);
remove(tr[p].l,key);
}
}
else p=0;
}
else if(tr[p].key>key) //左右递归寻找key
remove(tr[p].l,key);
else
remove(tr[p].r,key);
pushup(p);
}
int get_rank(int &p,int key)
{
if(!p) return 0;
if(tr[p].key==key) return tr[tr[p].l].size+1;
if(tr[p].key>key) return get_rank(tr[p].l,key); //左子树中的排名
else return tr[tr[p].l].size+1+get_rank(tr[p].r,key); //左子树大小+p+右子树排名
}
int get_key(int &p,int rank)
{
if(!p) return -INF;
if(tr[tr[p].l].size>=rank) return get_key(tr[p].l,rank);
if(rank==tr[tr[p].l].size+1) return tr[p].key;
else return get_key(tr[p].r,rank-tr[tr[p].l].size-1);
}
int get_prev(int &p,int key)
{
if(!p) return -INF;
if(tr[p].key>=key) return get_prev(tr[p].l,key);
else return max(tr[p].key,get_prev(tr[p].r,key));
}
int get_next(int &p,int key)
{
if(!p) return INF;
if(tr[p].key<=key) return get_next(tr[p].r,key);
else return min(tr[p].key,get_next(tr[p].l,key));
}
int main()
{
build();
cin>>t;
while(t--)
{
int op,x;
cin>>op>>x;
if(op==1) cout<<get_rank(root,x)-1<<endl;
if(op==2) cout<<get_key(root,x+1)<<endl;
if(op==3) cout<<get_prev(root,x)<<endl;
if(op==4) cout<<get_next(root,x)<<endl;
if(op==5) insert(root,x);
}
return 0;
}