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;
}
posted @ 2024-07-08 21:31  ppllxx_9G  阅读(17)  评论(0编辑  收藏  举报