Splay版本的会补。。。
在学了2个小时Splay之后深感Treap的优越
特地又花了20分钟打了个Treap
至于这些平衡树的优缺点 可以用平衡方式来直观的感受到
现在平衡树们面对着这样的一个问题:“二叉搜索树退化成O(n)”怎么办
Splay说:下面退不退化我不管 我把要查询的点转到根节点上
替罪羊树说:我看哪块不平衡了 我就把它拍扁重建弄成平衡的
SBT说:我旋转强行让深度为logn
RBT说:我手动给每个点打标签让他们出现各种性质然后旋转
而Treap说:在座的各位都是辣鸡 普通的二叉查找树对于随机数据不是平衡的吗?我随机给每个点分派一个数据 让整棵树对于这个随机数据平衡
Splay&替罪羊树&SBT&RBT:Orz
大概就是这样吧
#include<cstdio> #include<iostream> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> #include<vector> #include<queue> using namespace std; const int maxn=100010; const int inf=1e9; const int mod=1000000; inline int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)){if(ch=='0')f=-f;ch=getchar();} while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();} return x*f; } struct Treenode { int l,r,v,rnd,size,w; }; inline int ran() { static int seed=1364684679; seed+=(seed<<2)+1; return seed; } struct Treap { Treenode tr[maxn]; int root,Size,ans; inline void update(int k){tr[k].size=tr[tr[k].l].size+tr[tr[k].r].size+tr[k].w;} inline void Leftr(int &k) { int t=tr[k].r; tr[k].r=tr[t].l; tr[t].l=k; tr[t].size=tr[k].size; update(k); k=t; } inline void Rightr(int &k) { int t=tr[k].l; tr[k].l=tr[t].r; tr[t].r=k; tr[t].size=tr[k].size; update(k); k=t; } inline void insert(int &k,int x) { if(k==0) { Size++; k=Size; tr[k].size=tr[k].w=1 ; tr[k].v=x; tr[k].rnd=ran(); return; } tr[k].size++; if(tr[k].v==x)tr[k].w++; else if(x>tr[k].v) { insert(tr[k].r,x) ; if(tr[tr[k].r].rnd<tr[k].rnd)Leftr(k) ; } else { insert(tr[k].l,x) ; if(tr[tr[k].l].rnd<tr[k].rnd)Rightr(k) ; } } inline void del(int &k,int x) { if(k==0) return; if(tr[k].v==x) { if(tr[k].w>1) {tr[k].w--,tr[k].size--;return;} if(tr[k].l*tr[k].r==0)k=tr[k].l+tr[k].r; else if(tr[tr[k].l].rnd<tr[tr[k].r].rnd){Rightr(k);del(k,x);} else{Leftr(k);del(k,x);} } else if(x>tr[k].v){tr[k].size--;del(tr[k].r,x);} else{tr[k].size--;del(tr[k].l,x);} } inline int query_rank(int k,int x) { if(k==0) return 0; if(tr[k].v==x) return tr[tr[k].l].size+1 ; else if(x>tr[k].v) return tr[tr[k].l].size+tr[k].w+query_rank(tr[k].r,x) ; else return query_rank(tr[k].l,x) ; } inline int query_num(int k,int x) { if(k==0) return 0; if(x<=tr[tr[k].l].size)return query_num(tr[k].l ,x) ; else if(x>tr[tr[k].l].size+tr[k].w)return query_num(tr[k].r,x-tr[tr[k].l].size-tr[k].w); else return tr[k].v; } inline void query_pro(int k,int x) { if(k==0)return; if(tr[k].v<x) { ans=k ; query_pro(tr[k].r,x); } else query_pro(tr[k].l,x); } inline void query_sub(int k,int x) { if(k==0) return; if(tr[k].v>x) { ans=k; query_sub(tr[k].l,x); } else query_sub(tr[k].r,x); } }treap; int main() { int n; scanf("%d",&n); int op,x; for(int i=1;i<=n;i++) { scanf("%d%d",&op,&x); if(op==1)treap.insert(treap.root,x); if(op==2)treap.del(treap.root,x); if(op==3)printf("%d ",treap.query_rank(treap.root,x)); if(op==4)printf("%d ",treap.query_num(treap.root,x)); if(op==5){treap.ans=0;treap.query_pro(treap.root,x);printf("%d ",treap.tr[treap.ans].v);} if(op==6){treap.ans=0;treap.query_sub(treap.root,x);printf("%d ",treap.tr[treap.ans].v);} } }