宏定义
#define TT int:以 TT 为基本类型维护,可根据自己需要定义,这里实现了以 int 为基本类型的 Treap。
#define pl a[p].l:Treap 中左子树的简写。
#define pr a[p].r:Treap 中右子树的简写。
#define pv a[p].val:a[p].val 的简写。
#define pc a[p].cnt:a[p].cnt 的简写。
#define ps a[p].size:a[p].size 的简写。
#define pd a[p].dat:a[p].dat 的简写。
常量与变量
- const TT
INF:一个极值,能保证值为 INF 的节点的右子树没有元素,值为 −INF 的节点的左子树没有元素。
- int
tot:实际存在的节点个数,初始时有两个节点(1,−INF) 和 (2,INF)。
- int
nc[i]:第 i 个内存(没有被占用的节点)。
- int
root:Treap 的根节点,一般为 1。
- Tree
a[i]:Treap 的一个节点 i。
- int
a[i].l:节点 i 的左子节点,没有则为 0。
- int
a[i].r:节点 i 的右子节点,没有则为 0
- BST_T
a[i].val:节点 i 的值。
- int
a[i].cnt:与节点 i 的值相同的元素个数,都合并在 ai 中。
- int
a[i].size:以节点 i 为根的子树的元素总数(值相同的不算作一个)。
- int
a[i].dat:随机的额外权值,以确定 Treap 的形态。
函数
- int
compare(BST_T x,BST_T y):比较 x 与 y 的值,可根据需要自己定义。若返回值是一个负整数,如 −1,则表示 x 的值应该位于值为 y 的节点的左子树;若返回值是 0,则表示 x 的值应该和 y 属于同一个节点;若返回值是一个正整数,如 1,则表示 x 的值应该位于值为 y 的节点的右子树。
- void
update(int p):更新 p 节点的 ap.size。
- int
get_new(BST_T val):新建一个值为 val 的节点,返回这个节点的编号。
- int
del(int p):删除 p 节点,放入内存。
- void
build():重建树,重整内存。
- int
get(int p,BST_T val):找到以 p 为根的子树中值为 val 的节点的编号,没有则返回值为 0,调用时 p 常为 root。
- void
zig(int &p):右旋 p 节点。
- void
zag(int &p):左旋 p 节点。
- void
insert(int &p,BST_T val):在以 p 为根的子树中插入一个值为 val 的元素,计重,调用时 p 常为 root。
- void
remove(int &p,BST_T val):在以 p 为根的子树中删除一个值为 val 的元素,重复的只删一个,调用时 p 常为 root。
- int
get_pre(BST_T val):找到 Treap 中值为 val 的元素的前驱的节点编号,即小于 val 的数中最大的元素值的节点编号,不存在则返回值为 −INF 的节点的编号 1。
- int
get_next(BST_T val):找到 Treap 中值为 val 的元素的后继的节点编号,即大于 val 的数中最小的元素值的节点编号,不存在则返回值为 INF 的节点的编号 2。
- int
V_to_R(int p,BST_T val):在以 p 为根的子树中寻找值为 val 的元素的排名,不存在则返回 0,排名就是小于 val 后继的元素个数,调用时 p 常为 root。
- BST_T
R_to_V(int p,int rank):在以 p 为根的子树中寻找排名为 rank−1 的元素的值,不存在则返回 MAX,一个元素的排名可能有多个,调用时 p 常为 root。
- void
write(int p):输出以 p 节点为根节点的子树的信息,按先序遍历输出,每个节点的信息包括:该节点编号,该节点值,左子节点编号及值(无则均为 0),右子节点编号及值(无则均为 0)。
#define pl a[p].l
#define pr a[p].r
#define pv a[p].val
#define pc a[p].cnt
#define ps a[p].size
#define pd a[p].dat
struct Treap{
const TT INF=0x7fffffff;
int tot,root,nc[N];
struct Tree{
int l,r;
TT val;
int dat,cnt,size;
}a[N];
int compare(TT x,TT y){
if(x<y)
return -1;
if(x==y)
return 0;
if(x>y)
return 1;
}
void update(int p){
ps=a[pl].size+a[pr].size+pc;
}
int get_new(TT val){
int p=nc[++tot];
pv=val;
pc=ps=1;
pl=pr=0;
pd=rand();
return p;
}
void del(int &p){
nc[tot--]=p;
p=0;
}
void build(){
tot=0;
for(int i=1;i<N;i++)
nc[i]=i;
get_new(-INF);get_new(INF);
a[root=1].r=2;
update(root);
}
int get(int p,TT val){
if(!p)
return 0;
if(!compare(val,pv))
return p;
return get((compare(val,pv)<0?pl:pr),val);
}
void zig(int &p){
int q=pl;
pl=a[q].r;a[q].r=p;p=q;
update(pr);update(p);
}
void zag(int &p){
int q=a[p].r;
pr=a[q].l;a[q].l=p;p=q;
update(pl);update(p);
}
void insert(int &p,TT val){
if(!p){
p=get_new(val);
return;
}
if(!compare(val,pv)){
pc++;
update(p);
return;
}
if((compare(val,pv)<0)){
insert(pl,val);
if(pd<a[pl].dat)
zig(p);
}
else{
insert(pr,val);
if(pd<a[pr].dat)
zag(p);
}
update(p);
}
void remove(int &p,TT val){
if(p==0)
return;
if(!compare(val,pv)){
if(pc>1){
pc--;
update(p);
return;
}
if(pl||pr){
if(!pr||a[pl].dat>a[pr].dat){
zig(p);
remove(pr,val);
}
else{
zag(p);
remove(pl,val);
}
update(p);
return;
}
del(p);
return;
}
if((compare(val,pv)<0))
remove(pl,val);
else
remove(pr,val);
update(p);
}
int get(int p,int val){
if(!p)
return 0;
if(val==pv)
return p;
return get((val<pv?pl:pr),val);
}
int get_pre(TT val){
int ans=1,p=root;
while(p){
if(!compare(val,pv)){
if(pl){
p=pl;
while(pr)
p=pr;
ans=p;
}
break;
}
if((compare(pv,val)<0&&compare(pv,a[ans].val)>0))
ans=p;
p=(compare(val,pv)<0?pl:pr);
}
return ans;
}
int get_next(TT val){
int ans=2,p=root;
while(p){
if(!compare(val,pv)){
if(pr){
p=pr;
while(pl)
p=pl;
ans=p;
}
break;
}
if((compare(pv,val)>0&&compare(pv,a[ans].val)<0))
ans=p;
p=(compare(val,pv)<0?pl:pr);
}
return ans;
}
int V_to_R(int p,TT val){
if(!p)
return 0;
if(!compare(val,pv))
return a[pl].size;
if(compare(val,pv)<0)
return V_to_R(pl,val);
return V_to_R(pr,val)+a[pl].size+pc;
}
TT R_to_V(int p,int rank){
if(!p)
return INF;
if(a[pl].size>=rank)
return R_to_V(pl,rank);
if(a[pl].size+pc>=rank)
return pv;
return R_to_V(pr,rank-a[pl].size-pc);
}
void write(int p){
if(!p)
return;
printf("%d val:%d lson:%d %d rson:%d %d\n",p,pv,pl,a[pl].val,pr,a[pr].val);
write(pl);write(pr);
}
}tree;