FHQ Treap,又称无旋treap,一种不基于旋转机制的平衡树,可支持所有有旋treap、splay等能支持的操作(只有在LCT中会比splay复杂度多一个log)。最重要的是,它是OI中唯一一种支持可持久化的平衡树。
以下只提供题表与代码,不提供教程。
1.[BZOJ3224]普通平衡树
FHQ Treap的应用一:基础平衡树操作模板题。
由于merge、split和树高是$O(\log n)$的,所以所有基础操作都是$O(\log n)$的。
1 #include<cstdio> 2 #include<algorithm> 3 #define P pair<int,int> 4 #define rep(i,l,r) for (int i=l; i<=r; i++) 5 using namespace std; 6 7 const int N=200100,inf=1000000000; 8 int T,nd,rt,op,ans,x,ls[N],rs[N],h[N],sz[N],v[N]; 9 10 void upd(int x){ sz[x]=sz[ls[x]]+sz[rs[x]]+1; } 11 int get(int x){ v[++nd]=x; sz[nd]=1; h[nd]=rand(); return nd; } 12 13 int merge(int x,int y){ 14 if (!x || !y) return x+y; 15 if (h[x]<h[y]) { rs[x]=merge(rs[x],y); upd(x); return x; } 16 else { ls[y]=merge(x,ls[y]); upd(y); return y; } 17 } 18 19 P split(int x,int k){ 20 if (!x) return P(0,0); 21 P tmp; 22 if (k<=sz[ls[x]]) tmp=split(ls[x],k),ls[x]=tmp.second,upd(x),tmp=P(tmp.first,x); 23 else tmp=split(rs[x],k-sz[ls[x]]-1),rs[x]=tmp.first,upd(x),tmp=P(x,tmp.second); 24 return tmp; 25 } 26 27 int rank(int x,int k){ 28 if (!x) return 0; 29 if (v[x]>=k) return rank(ls[x],k); else return rank(rs[x],k)+sz[ls[x]]+1; 30 } 31 32 int find(int x,int k){ 33 if (!x) return 0; 34 if (k==sz[ls[x]]+1) return x; 35 if (k<=sz[ls[x]]) return find(ls[x],k); else return find(rs[x],k-sz[ls[x]]-1); 36 } 37 38 void ins(int k){ 39 int v=rank(rt,k); P x=split(rt,v); 40 rt=merge(merge(x.first,get(k)),x.second); 41 } 42 43 void del(int k){ 44 int v=rank(rt,k); 45 P x=split(rt,v),y=split(x.second,1); 46 rt=merge(x.first,y.second); 47 } 48 49 int main(){ 50 for (scanf("%d",&T); T--; ){ 51 scanf("%d%d",&op,&x); 52 if (op==1) ins(x); 53 if (op==2) del(x); 54 if (op==3) printf("%d\n",rank(rt,x)+1); 55 if (op==4) printf("%d\n",v[find(rt,x)]); 56 if (op==5) printf("%d\n",v[find(rt,rank(rt,x))]); 57 if (op==6) printf("%d\n",v[find(rt,rank(rt,x+1)+1)]); 58 } 59 return 0; 60 }