treap是一棵拥有键值、优先级、两种权值的树。对于键值而言,这棵树是排序二叉树;对于优先级而言,这棵树就是堆,即在这棵树的任意子树中根节点的优先值是最大的。treap树可以实现插入,删除节点,查询K大排名,查询数的排名,查询前驱和后继。
定义:
struct Node
{
Node*ch[2];
int r,v,s,num; //r为优先级, v是这个节点的权值, s代表这棵树的大小, num保存的时这个节点数的个数,也就是这个节点相同的数的个数.
Node(int v):v(v) {r=rand(); ch[0]=ch[1]=NULL; num=1;}
int cmp(int x) const{
if(x==v) return -1;
else return (x>v?1:0);
}
void Maintain(){
s=num;
if(ch[0]!=NULL) s+=ch[0]->s;
if(ch[1]!=NULL) s+=ch[1]->s;
}
};
Node* root;
加入节点:
void insert(Node* &o,int x)
{
if(o==NULL) o=new Node(x);
else
{
int d=o->cmp(x);
if(d==-1) o->num+=1;
else
{
insert(o->ch[d],x);
if(o->r < o->ch[d]->r) rotate(o,d^1);
}
}
o->Maintain();
}
删除节点:
void del(Node* &o,int x)
{
int d=o->cmp(x);
if(d==-1)
{
if(o->num==1)
{
if(o->ch[0]==NULL) o=o->ch[1];
else if(o->ch[1]==NULL) o=o->ch[0];
else
{
int d2=(o->ch[1]->r > o->ch[0]->r?0:1);
rotata(o,d2); del(o->ch[d2],x);
}
}
else o->num-=1;
}
else del(o->ch[d],x);
if(o!=NULL) o->Maintain();
}
查询一个数的排名:
int rank(Node* &o,int x)
{
int d=o->cmp(x);
if(d==-1) return (o->ch[0]==NULL?1:o->ch[0]->s+1);
else
{
if(d==0) return rank(o->ch[0],x);
else return (rank(o->ch[1],x)+(o->ch[0]==NULL?o->num:o->ch[0]->s+o->num));
}
}
查询排名为K的数:
int kth(Node* &o,int x)
{
if(o==NULL||o->s<x||x<=0) return 0;
int d=(o->ch[0]==NULL?0:o->ch[0]->s);
if(d+1<=x&&x<=d+o->num) return o->v;
if(x<=d) return kth(o->ch[0],x);
else return kth(o->ch[1],x-d-o->num);
}
查询一个数的前驱:
void pre(Node* &o,int x)
{
<span style="white-space:pre"> </span>if(o!=NULL)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span> if(x<=o->v)
<span style="white-space:pre"> </span> {
<span style="white-space:pre"> </span> if(o->ch[0]!=NULL) pre(o->ch[0],x);
}
else
{
<span style="white-space:pre"> </span> ans=max(ans,o->v);
<span style="white-space:pre"> </span> if(o->ch[1]!=NULL) pre(o->ch[1],x);
}
}
}
//ans为一个全局变量,与下面查询后继时的一样
查询一个数的后继:
void sub(Node* &o,int x)
{
if(o!=NULL)
{
if(x>=o->v)
{
if(o->ch[1]!=NULL) sub(o->ch[1],x);
}
else
{
ans=min(ans,o->v);
if(o->ch[0]!=NULL) sub(o->ch[0],x);
}
}
}
当然treap还可以进行合并之类的操作,具体的会在永无乡中提到.