FHQ_Treap
平衡树
目前之学了两种:splay 和 treap,treap 直接学的 FHQ 的无旋 treap,太好用了。
splay 在以后学 LCT 的时候可能会用,但是也能用 FHQ-treap 实现。
本文不会涉及复杂度证明,尤其是 splay 的,如有需求,请查阅 oiwiki。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int n;
int rt,sz[N],son[N][2],va[N],pri[N],tot;
namespace FHQ
{
inline void pushup(int k) {sz[k]=sz[son[k][0]]+sz[son[k][1]]+1;}
int merge(int x,int y)
{
if(!x||!y) return x|y;
if(pri[x]<=pri[y]) return son[x][1]=merge(son[x][1],y),pushup(x),x;
else return son[y][0]=merge(x,son[y][0]),pushup(y),y;
}
void split(int rt,int k,int &x,int &y)
{
if(!rt) return x=y=0,void(0);
if(va[rt]<=k) x=rt,split(son[x][1],k,son[x][1],y);
else y=rt,split(son[y][0],k,x,son[y][0]);
pushup(rt);
}
int kth(int rt,int k)
{
if(k<=sz[son[rt][0]]) return kth(son[rt][0],k);
if(k==sz[son[rt][0]]+1) return va[rt];
return kth(son[rt][1],k-sz[son[rt][0]]-1);
}
inline int nw(int k) {va[++tot]=k; sz[tot]=1; pri[tot]=rand(); return tot;}
inline void ins(int k)
{
int x,y;
split(rt,k,x,y); rt=merge(merge(x,nw(k)),y);
}
inline void del(int k)
{
int x,y,z;
split(rt,k,x,y); split(x,k-1,x,z);
z=merge(son[z][0],son[z][1]);
rt=merge(merge(x,z),y);
}
inline int rk(int k)
{
int x,y,res; split(rt,k-1,x,y);
res=sz[x]+1; rt=merge(x,y);
return res;
}
inline int pre(int k)
{
int x,y,res; split(rt,k-1,x,y);
res=kth(x,sz[x]); rt=merge(x,y);
return res;
}
inline int nxt(int k)
{
int x,y,res; split(rt,k,x,y);
res=kth(y,1); rt=merge(x,y);
return res;
}
} using namespace FHQ;
int main()
{
scanf("%d",&n);
while(n--)
{
int c,x; scanf("%d%d",&c,&x);
if(c==1) ins(x);
if(c==2) del(x);
if(c==3) printf("%d\n",rk(x));
if(c==4) printf("%d\n",kth(rt,x));
if(c==5) printf("%d\n",pre(x));
if(c==6) printf("%d\n",nxt(x));
}
return 0;
}