【模板】Treap
阿新 • • 發佈:2018-11-10
Treap,又稱樹堆,是一種通過堆性質來維持BST平衡的資料結構。具體體現在對於樹上每一個點來說,既有BST維護的值,又有一個堆維護的隨機生成的值。維護平衡性的辦法是根據堆維護的值的相對大小關係進行左旋和右旋這兩種操作,在旋轉的前後,依然滿足BST性質。
程式碼如下
#include <bits/stdc++.h> using namespace std; const int maxn=1e5+10; int ans; struct node{int lc,rc,val,cnt,size,rd;}; struct Treap{ #define ls t[x].lc #define rs t[x].rc node t[maxn]; int root,tot; Treap():root(0),tot(0){} ~Treap(){} inline int newnode(int val){ ++tot,t[tot].size=t[tot].cnt=1,t[tot].val=val,t[tot].rd=rand(); return tot; } inline void pushup(int x){ t[x].size=t[ls].size+t[rs].size+t[x].cnt; } inline void zig(int &x){ int lson=ls; ls=t[lson].rc,t[lson].rc=x,x=lson; pushup(t[lson].rc),pushup(x); } inline void zag(int &x){ int rson=rs; rs=t[rson].lc,t[rson].lc=x,x=rson; pushup(t[rson].lc),pushup(x); } void insert(int &x,int val){ if(!x)x=newnode(val); else if(val==t[x].val)++t[x].cnt,++t[x].size; else if(val<t[x].val){ ++t[x].size,insert(ls,val); if(t[ls].rd<t[x].rd)zig(x); }else{ ++t[x].size,insert(rs,val); if(t[rs].rd<t[x].rd)zag(x); } } void del(int &x,int val){ if(!x)return; else if(val==t[x].val){ if(t[x].cnt>1)--t[x].cnt,--t[x].size; else if(!ls||!rs)x=ls+rs; else if(t[ls].rd<t[rs].rd)zig(x),del(x,val); else zag(x),del(x,val); } else if(val<t[x].val)--t[x].size,del(ls,val); else --t[x].size,del(rs,val); } int getrank(int x,int val){ if(val<t[x].val)return getrank(ls,val); else if(val>t[x].val)return getrank(rs,val)+t[ls].size+t[x].cnt; else return t[ls].size+1; } int kth(int x,int k){ if(k<=t[ls].size)return kth(ls,k); else if(k>t[ls].size+t[x].cnt)return kth(rs,k-t[ls].size-t[x].cnt); else return t[x].val; } void pre(int x,int val){ if(!x)return; else if(t[x].val<val)ans=t[x].val,pre(rs,val); else pre(ls,val); } void nxt(int x,int val){ if(!x)return; else if(t[x].val>val)ans=t[x].val,nxt(ls,val); else nxt(rs,val); } }treap; int main(){ int n;scanf("%d",&n); while(n--){ int opt,val;scanf("%d%d",&opt,&val); switch(opt){ case 1:treap.insert(treap.root,val);break; case 2:treap.del(treap.root,val);break; case 3:printf("%d\n",treap.getrank(treap.root,val));break; case 4:printf("%d\n",treap.kth(treap.root,val));break; case 5:treap.pre(treap.root,val);printf("%d\n",ans);break; case 6:treap.nxt(treap.root,val);printf("%d\n",ans);break; } } return 0; }