FHQ treap

每个点维护两个权值:\(\text{val},\text{pri}\),其中 \(\text {val}\) 满足二叉搜索树性质,\(\text{pri}\) 满足大根堆。
\(\text{pri}\) 是随机生成的。

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<random>
using namespace std;
mt19937 rnd(time(0));
const int N=1e6+10;
int cnt,rt;
int ls[N],rs[N],val[N],pri[N],siz[N];
void update(int u) {
	siz[u]=siz[ls[u]]+siz[rs[u]]+1;
}
void addn(int x) {
	siz[++cnt]=1,val[cnt]=x,pri[cnt]=rnd()%N,ls[cnt]=rs[cnt]=0;
}
void split(int u,int x,int &L,int &R) {
	if(u==0) {L=R=0; return ;}
	if(val[u]<=x) {
		L=u;
		split(rs[u],x,rs[u],R);
	} else {
		R=u;
		split(ls[u],x,L,ls[u]);
	}
	update(u);
}
int merge(int L,int R) {
	if(L==R) return L;
	if(L==0||R==0) return L^R;
	if(pri[L]>pri[R]) {
		rs[L]=merge(rs[L],R);
		update(L); return L;
	} else {
		ls[R]=merge(L,ls[R]);
		update(R); return R;
	}
}
void ins(int x) {
	int L,R;
	split(rt,x,L,R);
	addn(x);
	int tmp=merge(L,cnt);
	rt=merge(tmp,R);
}
void del(int x) {
	int L,R,p;
	split(rt,x,L,R);
	split(L,x-1,L,p);
	p=merge(ls[p],rs[p]);
	rt=merge(merge(L,p),R);
}
int rnk(int x) {
	int L,R,Ans;
	split(rt,x-1,L,R);
	Ans=siz[L]+1;
	rt=merge(L,R);
	return Ans;
}
int kth(int u,int k) {
	if(k==siz[ls[u]]+1) return u;
	else if(k<=siz[ls[u]]) return kth(ls[u],k);
	else return kth(rs[u],k-siz[ls[u]]-1);
}
int pre(int x) {
	int L,R;
	split(rt,x-1,L,R);
	int Ans=val[kth(L,siz[L])];
	rt=merge(L,R);
	return Ans;
}
int suf(int x) {
	int L,R;
	split(rt,x,L,R);
	int Ans=val[kth(R,1)];
	rt=merge(L,R);
	return Ans;
}
int main() {
	int n; scanf("%d",&n);
	for(; n; n--) {
		int op,x; scanf("%d%d",&op,&x);
		switch(op) {
			case 1: ins(x); break;
			case 2: del(x); break;
			case 3: printf("%d\n",rnk(x)); break;
			case 4: printf("%d\n",val[kth(rt,x)]); break;
			case 5: printf("%d\n",pre(x)); break;
			case 6: printf("%d\n",suf(x)); break;
		}
	}
	return 0;
}
posted @ 2023-10-02 20:19  s1monG  阅读(10)  评论(0编辑  收藏  举报