当然,秒懂的前提是,你看了我的前一篇文章:
我是传送门
其实treap树能平衡的巧妙之处就在于,它利用了随机化权和堆性质来巧妙地控制zig&&zag的使用时机,能达到我们所期望的平衡。
ckick_Me_to_view_the_question
friendly commented codes:
#include<bits/stdc++.h>
#define oo INT_MAX
#define maxn 50000
#define _rep(i, a, b) for(int i = (a); i <= (b); ++i)
#define _for(i, a, b) for(int i = (a); i < (b) ;++i)
using namespace std;
struct Treap
{
int l, r, val, rnd;
int cnt, size;
}a[maxn];
int cnt, root, n;
int __new(int val){
a[++cnt].val = val;
a[cnt].rnd = rand();
a[cnt].cnt = a[cnt].size = 1;
return cnt;
}
void __upd(int p){
a[p].size = a[a[p].l].size + a[a[p].r].size + a[p].cnt;
}
void __init__(){
__new(-oo), __new(oo);
root = 1, a[1].r = 2;
__upd(root);
}
void zig(int &p){
int q = a[p].l;
a[p].l = a[q].r, a[q].r = p, p = q;
__upd(a[p].r), __upd(p);
}
void zag(int &p){
int q = a[p].r;
a[p].r = a[q].l, a[q].l = p, p = q;
__upd(a[p].l), __upd(p);
}
void __ins(int &p, int val){
if(p == 0){
p = __new(val);
return;
}
if(val == a[p].val){
a[p].cnt++, __upd(p);
return ;
}
if(val < a[p].val){
__ins(a[p].l, val);
if(a[p].rnd < a[a[p].l].rnd) zig(p);
} else {
__ins(a[p].r, val);
if(a[p].rnd < a[a[p].r].rnd) zag(p);
}
__upd(p);
}
int __pre(int val){
int ans = 1;
int p = root;
while(p){
if(a[p].val == val){
if(a[p].l){
p = a[p].l;
while(a[p].r)p = a[p].r;
ans = p;
}
break;
}
if(a[p].val < val && a[p].val > a[ans].val) ans = p;
p = val < a[p].val ? a[p].l : a[p].r;
}
return a[ans].val;
}
int __nxt(int val){
int ans = 2;
int p = root;
while (p)
{
if(a[p].val == val){
if(a[p].r){
p = a[p].r;
while(a[p].l)p = a[p].l;
ans = p;
}
break;
}
if(a[p].val > val && a[ans].val > a[p].val) ans = p;
p = val < a[p].val ? a[p].l : a[p].r;
}
return a[ans].val;
}
void __del(int &p, int val){
if(p == 0)return;
if(a[p].val == val){
if(a[p].cnt > 1){
a[p].cnt--, __upd(p);
return;
}
if(a[p].l || a[p].r){
if(a[p].r == 0 || a[a[p].l].rnd > a[a[p].r].rnd){
zig(p), __del(a[p].r, val);
}else {
zag(p), __del(a[p].l, val);
}
__upd(p);
}else p = 0;
return;
}
val < a[p].val ? __del(a[p].l, val) : __del(a[p].r, val);
__upd(p);
}
int __rankbyval(int p, int val){
if(p == 0)return 0;
if(a[p].val == val) return a[a[p].l].size + 1;
if(val < a[p].val) return __rankbyval(a[p].l, val);
return __rankbyval(a[p].r, val) + a[a[p].l].size + a[p].cnt;
}
int __valbyrank(int p,int rank){
if(p == 0) return oo;
if(a[a[p].l].size >= rank) return __valbyrank(a[p].l, rank);
if(a[a[p].l].size + a[p].cnt >= rank) return a[p].val;
return __valbyrank(a[p].r, rank - a[a[p].l].size - a[p].cnt);
}
int main(){
ios::sync_with_stdio(0);
__init__();
int n, op, x;
cin >> n;
_rep(i, 1, n){
cin >> op >> x;
switch (op)
{
case 1:
__ins(root, x);
break;
case 2:
__del(root, x);
break;
case 3:
cout << __rankbyval(root, x) - 1 << endl;
break;
case 4:
cout << __valbyrank(root, x + 1) << endl;
break;
case 5:
cout << __pre(x) << endl;
break;
case 6:
cout << __nxt(x) << endl;
break;
default:
break;
}
}
system("pause");
}
以上代码可以作为treap平衡树的模板,如果你不嫌弃的话
在大部分情况下,用treap实现的平衡树不会被卡掉,很少有人出题会卡这个,但是我还是建议,多用splay,splay的拓展性好,是一种比treap更为常见的平衡树,虽然treap比splay简单;
以下是splay的 博客,以后补坑