1. 程式人生 > >「模板」 FHQ_Treap

「模板」 FHQ_Treap

ase ras 目前 ++ cst UC cstring 謝謝 sign

「模板」 FHQ_Treap

<題目鏈接>


我也是偶然發現我還沒發過FHQ_Treap的板子。

那就發一波吧。

這個速度實在不算快,但是不用旋轉,並且好寫

更重要的是,Splay 可以做的事情它都可以做!比如區間操作,以及LCT相關…

而且它還可以可持久化!(雖然目前還沒有學)

Capella 認為,不涉及區間操作時,用快一些的平衡樹(SBT/Treap/替罪羊...)較好,涉及區間操作而又不想寫大量代碼的話,FHQ_Treap 不失為一種極好的選擇。

下一篇寫 FHQ_Treap 的區間操作。

#include <cstdio>
#include <cstdlib>
#include <cstring> #include <ctime> const int MAXN=100010; int n; class FHQ_Treap { public: int rt; FHQ_Treap(void) { rt=cnt=0; memset(a,0,sizeof a); memset(s,0,sizeof s); } void Insert(int x) { int
l=0,r=0,t=0; MakeNode(t,x),Split(rt,x,l,r); Merge(l,l,t),Merge(rt,l,r); } void Erase(int x) { int l=0,r=0,t=0; Split(rt,x,l,r),Split(l,x-1,l,t); Merge(t,s[t].c[0],s[t].c[1]),Merge(l,l,t),Merge(rt,l,r); } int
Rank(int x) { int l=0,r=0,ans; Split(rt,x-1,l,r),ans=s[l].size+1,Merge(rt,l,r); return ans; } int Find(int i,int x) { int t; while(x!=(t=s[s[i].c[0]].size+1)) if(x<t) i=s[i].c[0]; else x-=t,i=s[i].c[1]; return s[i].v; } int Pre(int x) { int l=0,r=0,ans; Split(rt,x-1,l,r),ans=Find(l,s[l].size),Merge(rt,l,r); return ans; } int Next(int x) { int l=0,r=0,ans; Split(rt,x,l,r),ans=Find(r,1),Merge(rt,l,r); return ans; } private: bool a[MAXN]; int cnt; struct node { int v,p,size,c[2]; }s[MAXN]; int Random(void) { int x; while(a[x=rand()%MAXN]); a[x]=1; return x; } void Update(int i) { s[i].size=s[s[i].c[0]].size+s[s[i].c[1]].size+1; } void MakeNode(int &i,int x) { s[i=++cnt].v=x,s[i].p=Random(),s[i].size=1; } void Split(int i,int x,int &l,int &r) { if(!i) { l=r=0; return; } else if(x<s[i].v) Split(s[r=i].c[0],x,l,s[i].c[0]); else Split(s[l=i].c[1],x,s[i].c[1],r); Update(i); } void Merge(int &i,int l,int r) { if(!l || !r) { i=l|r; return; } else if(s[l].p>s[r].p) Merge(s[i=l].c[1],s[l].c[1],r); else Merge(s[i=r].c[0],l,s[r].c[0]); Update(i); } }T; int main(int argc,char *argv[]) { srand((unsigned)time(NULL)); scanf("%d",&n); for(int i=1,opt,x;i<=n;++i) { scanf("%d %d",&opt,&x); switch(opt) { case 1: T.Insert(x); break; case 2: T.Erase(x); break; case 3: printf("%d\n",T.Rank(x)); break; case 4: printf("%d\n",T.Find(T.rt,x)); break; case 5: printf("%d\n",T.Pre(x)); break; case 6: printf("%d\n",T.Next(x)); break; } } return 0; }

謝謝閱讀。

「模板」 FHQ_Treap