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;
}