treap 51pts 求调
查看原帖
treap 51pts 求调
531197
lzh123bc楼主2024/8/29 22:55

rt

思路与第一篇题解大致相同,不过我建的是小根堆

//-std=c++14 -O2 -Wl,-stack=536870912 -Wall -Wextra
#include <bits/stdc++.h>
#define debug(x) cerr<<"deb "<<__LINE__<<':'<<#x<<'='<<(x)<<endl
#define int long long
#define end putchar('\n')
#define ret return
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
const int N=500010,M=100010,INF=9223372036854775807,Mod=998244353;
const double pi=acos(-1.0);
using namespace std;
inline int read(){
	int s=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
	ret s*f;
}
inline int exgcd(int a,int b,int &x,int &y){
	if(b==0){x=1;y=0;ret a;}
	int r=exgcd(b,a%b,x,y);
	int t=x;x=y;y=t-a/b*y;
	ret r;
}
int tot=0,root=0;
struct Dot{int kid[2],rk,val,siz,sum;}a[N];
// kid 子节点 rd 随机值 val 当前节点值 siz 子树大小 sum 值的个数
// kid 0 左儿子 1 右儿子
int build(int v){//建新节点
	++tot;a[tot].val=v;
	a[tot].rk=rand()*rand()%Mod;
	a[tot].siz=1;
	a[tot].sum=1;
	ret tot;
}
void change(int cur){a[cur].siz=a[a[cur].kid[0]].siz+a[a[cur].kid[1]].siz+a[cur].sum;}//改变子树大小
void rotate(int &cur,int k){//左旋 0 右旋 1 
	int d=a[cur].kid[k^1];
	a[cur].kid[k^1]=a[d].kid[k];
	a[d].kid[k]=cur;cur=d;
	change(cur);change(a[cur].kid[k]);change(a[cur].kid[k^1]);ret;
}
void insert(int &cur,int v){
	if(!cur){cur=build(v);ret;}
	if(v==a[cur].val)a[cur].sum++;
	else if(v<a[cur].val){insert(a[cur].kid[0],v);if(a[cur].rk>a[a[cur].kid[0]].rk)rotate(cur,1);}
	else{insert(a[cur].kid[1],v);if(a[cur].rk>a[a[cur].kid[1]].rk)rotate(cur,0);}
	change(cur);ret;
}
void remove(int &cur,int v){
	if(!cur)ret;
	if(v==a[cur].val){
		if(a[cur].sum>1){a[cur].sum--;change(cur);ret;}
		if((!a[cur].kid[0])&&(!a[cur].kid[0])){cur=0;ret;}
		if((!a[cur].kid[1])||a[a[cur].kid[0]].rk<a[a[cur].kid[1]].rk)rotate(cur,1),remove(a[cur].kid[1],v);
		else rotate(cur,0),remove(a[cur].kid[0],v);
		change(cur);
	}
	else if(v<a[cur].val)remove(a[cur].kid[0],v);
	else remove(a[cur].kid[1],v);
	change(cur);ret;
}
int Rank(int cur,int v){
	if(!cur)ret 1;
	if(v<a[cur].val)ret Rank(a[cur].kid[0],v);
	if(v>a[cur].val)ret Rank(a[cur].kid[1],v)+a[cur].sum+a[a[cur].kid[0]].siz;
	ret a[a[cur].kid[0]].siz+1;
}
int getkh(int cur,int rank){
	if(!cur)ret INF;
	if(rank<=a[a[cur].kid[0]].siz)ret getkh(a[cur].kid[0],rank);
	if(rank<=a[a[cur].kid[0]].siz+a[cur].sum)ret a[cur].val;
	ret getkh(a[cur].kid[1],rank-a[a[cur].kid[0]].siz-a[cur].sum);
}
int pre(int v){
	int cur=root,rt;
	while(cur){
		if(a[cur].val<v)rt=a[cur].val,cur=a[cur].kid[1];
		else cur=a[cur].kid[0];
	}
	ret rt;
}
int nxt(int v){
	int cur=root,rt;
	while(cur){
		if(a[cur].val>v)rt=a[cur].val,cur=a[cur].kid[0];
		else cur=a[cur].kid[1];
	}
	ret rt;
}
signed main(){
	srand(time(0));
	int t=read();insert(root,INF);insert(root,-INF);
	while(t--){
		int op=read(),val=read();
		if(op==1)insert(root,val);
		if(op==2)remove(root,val);
		if(op==3)printf("%lld\n",Rank(root,val)-1);
		if(op==4)printf("%lld\n",getkh(root,val+1));
		if(op==5)printf("%lld\n",pre(val));
		if(op==6)printf("%lld\n",nxt(val));
	}
	ret 0;
}
2024/8/29 22:55
加载中...