「模板」 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;
}
谢谢阅读。