P3369 【模板】普通平衡树

题目描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

  • 插入 x 数
  • 删除 x 数(若有多个相同的数,因只删除一个)
  • 查询 x 数的排名(排名定义为比当前数小的数的个数 +1 )
  • 查询排名为 x 的数
  • 求 x 的前驱(前驱定义为小于 x,且最大的数)
  • 求 x 的后继(后继定义为大于 x,且最小的数)

思路

代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<iomanip>

#define N 100010
#define INF 99999999
using namespace std;
int n,tot,root,pos;
struct qwe{
	int s[2],fa;
	int val;
	int siz,cnt;
}tr[N];

long long read(){
	long long x=0,h=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')h=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+(long long)(ch-'0');ch=getchar();}
	return x*h;
}

int typeson(int x){
	return tr[tr[x].fa].s[1]==x;
}

void clear(int id){
	tr[id].val=tr[id].s[0]=tr[id].s[1]=tr[id].fa=0;
	tr[id].siz=tr[id].cnt=0;
	return ;
}

void pushup(int id){
	tr[id].siz=tr[tr[id].s[0]].siz+tr[tr[id].s[1]].siz+tr[id].cnt;
}

void link(int f,int x,int tp){
	tr[x].fa=f; tr[f].s[tp]=x;
	return ;
}

void rotate(int x){
	int y=tr[x].fa,z=tr[y].fa;
	int tp=typeson(x);
	link(y,tr[x].s[tp^1],tp);
	link(z,x,typeson(y));
	link(x,y,tp^1);
	pushup(y);
	pushup(x);
	return ;
}

void splay(int x,int gl){
	for( ;tr[x].fa!=gl; ){
		if(tr[tr[x].fa].fa!=gl&&typeson(x)==typeson(tr[x].fa))
			rotate(tr[x].fa);
		rotate(x);
	}
	if(gl==0)root=x;
	return ;
}

int new_p(int x,int f){
	tr[++tot].val=x;
	tr[tot].cnt=tr[tot].siz=1;
	tr[tot].fa=f;
	return tot;
}

int query_r(int id,int x,int op,int ans,int fr){
	if(id==0){
		splay(fr,0);
		return ans;
	}
	if(x==tr[id].val)return query_r(tr[id].s[op],x,op,ans,fr);
	if((x>tr[id].val)==op)return query_r(tr[id].s[op],x,op,ans,fr);
	else return query_r(tr[id].s[op^1],x,op,tr[id].val,id);
}

void insert(int id,int x){
	if(root==0){
		root=new_p(x,0);
		return ;
	}
	tr[id].siz++;
	if(tr[id].val==x){
		tr[id].cnt++;
		splay(id,0);
		return ;
	}
	int k=(x>tr[id].val);
	if(!tr[id].s[k]){
		tr[id].s[k]=new_p(x,id);
		splay(tr[id].s[k],0);
		return ;
	}
	insert(tr[id].s[k],x);
	pushup(id);
	return ;
}

void delt(int x){
	int ba;
	query_r(root,x,1,INF,2);
	ba=root;
	query_r(root,x,0,-INF,1);
	splay(ba,root);
	if(tr[tr[ba].s[0]].cnt>1){
		tr[tr[ba].s[0]].cnt--;
		tr[tr[ba].s[0]].siz--;
		splay(tr[ba].s[0],0);
	}
	else {
		clear(tr[ba].s[0]);
		tr[ba].s[0]=0;
		pushup(ba);
		splay(ba,0);
	}
	return ;
}

int query_rk(int id,int x,int fr){
	if(id==0){
		pos=fr;
		return 0;
	}
	if(tr[id].val>=x)return query_rk(tr[id].s[0],x,id);
	else if(tr[id].val<x)return query_rk(tr[id].s[1],x,id)+tr[tr[id].s[0]].siz+tr[id].cnt;
}

int query_val(int id,int x){
	if(x<=tr[tr[id].s[0]].siz)return query_val(tr[id].s[0],x);
	else if(x<=tr[tr[id].s[0]].siz+tr[id].cnt){
		splay(id,0);
		return tr[id].val;
	}
	else return query_val(tr[id].s[1],x-tr[tr[id].s[0]].siz-tr[id].cnt);
}

int main(){
	insert(root,-INF);insert(root,INF);
	n=read();
	for(int i=1;i<=n;i++){
		int op=read(),x=read();
		if(op==1) insert(root,x);
		else if(op==2) delt(x);
		else if(op==3) {
			printf("%d\n",query_rk(root,x,0));
			splay(pos,0);
		}
		else if(op==4) printf("%d\n",query_val(root,x+1));
		else if(op==5) printf("%d\n",query_r(root,x,0,-INF,1));
		else printf("%d\n",query_r(root,x,1,INF,2));
	}
	return 0;
}
posted @ 2022-03-23 18:41  Charisk_FOD  阅读(27)  评论(0编辑  收藏  举报