简介
树堆,在数据结构中也称Treap,是指有一个随机附加域满足堆的性质的二叉搜索树,其结构相当于以随机数据插入的二叉搜索树。其基本操作的期望时间复杂度为O(logn)。相对于其他的平衡二叉搜索树,Treap的特点是实现简单,且能基本实现随机平衡的结构。
实现
节点结构
#define lc(x) t[x].lc
#define rc(x) t[x].rc
#define v(x) t[x].key
#define p(x) t[x].pri
#define c(x) t[x].cnt
#define s(x) t[x].sze
struct node{
int lc;
int rc;
int key;
int pri;
int cnt;
int sze;
}t[100010];
int pool,rt;
节点信息更新
void update(const int k){
//update the treap
s(k)=s(lc(k))+s(rc(k))+c(k);
}
左旋
void zig(int &k){
//left
int y=lc(k);
lc(k)=rc(y);
rc(y)=k;
s(y)=s(k);
update(k);
k=y;
}
右旋
void zag(int &k){
//right
int y=rc(k);
rc(k)=lc(y);
lc(y)=k;
s(y)=s(k);
update(k);
k=y;
}
插入
void insert(int &k,const int key){
//insert a node
if(!k){
k=++pool;
v(k)=key;
p(k)=rand();
c(k)=s(k)=1;
lc(k)=rc(k)=0;
return;
}
s(k)++;
if(v(k)==key) ++c(k);
else if(key<v(k)){
insert(lc(k),key);
if(p(lc(k))<p(k)) zig(k); //satisfy the nature of the heap
}else{
insert(rc(k),key);
if(p(rc(k))<p(k)) zag(k); //satisfy the nature of the heap
}
}
删除
void remove(int &k,const int key){
//delete a node
if(v(k)==key){
if(c(k)>1) --c(k),--s(k);
else if(!lc(k)||!rc(k)) k=lc(k)+rc(k);
else if(p(lc(k))<p(rc(k))) zig(k),remove(k,key); //satisfy the nature of the heap
else zag(k),remove(k,key); //satisfy the nature of the heap
return;
}
s(k)--;
if(key<v(k)) remove(lc(k),key);
else remove(rc(k),key);
}
查询前驱(不大于指定值的最大值)
int querypre(const int key){
//lower
int x=rt,res=-10000001;
while(x){
if(v(x)<key) res=v(x),x=rc(x);
else x=lc(x);
}
return res;
}
查询后驱(不小于指定值的最小值)
int querynext(const int key){
//upper
int x=rt,res=-10000001;
while(x){
if(v(x)>key) res=v(x),x=lc(x);
else x=rc(x);
}
return res;
}
查询第K大的值
int querykth(int k){
int x=rt;
while(x){
if(s(lc(x))<k&&s(lc(x))+c(x)>=k) return v(x);
if(s(lc(x))>=k) x=lc(x);
else k-=s(lc(x))+c(x),x=rc(x);
}
return 0;
}
查询排名
int queryrank(const int key){
int x=rt,res=0;
while(x){
if(key==v(x)) return res+s(lc(x))+1;
if(key<v(x)) x=lc(x);
else res+=s(lc(x))+c(x),x=rc(x);
}
return res;
}