#include<bits/stdc++.h>
using namespace std;
const int maxn=2e6;
int n;
struct node
{
int num,num1,val,ch[3],key;
}shu[maxn];
int ans=0;
void up(int k)
{
shu[k].num=shu[shu[k].ch[0]].num+shu[shu[k].ch[1]].num+shu[k].num1;
}
void romate(int &k,int d)//这里的引用很关键 ,以地址思考问题 ,0是右旋
{
int son=shu[k].ch[d];
shu[k].ch[d]=shu[son].ch[d^1];
shu[son].ch[d^1]=k;
shu[son].num=shu[k].num;
up(k);
k=son;
}
void insert(int &k,int x)
{
if(k==0)
{
k=++ans;
shu[ans].val=x;
shu[ans].num=shu[ans].num1=1;
shu[ans].ch[1]=shu[ans].ch[0]=0;
shu[ans].key=rand();
return;
}
else
{
++shu[k].num;
if(x==shu[k].val)
{
shu[k].num1++;
return;
}
else if(x>shu[k].val)
{
insert(shu[k].ch[1],x);
if(shu[shu[k].ch[1]].key>shu[k].key) romate(k,1);
}
else
{
insert(shu[k].ch[0],x);
if(shu[shu[k].ch[0]].key>shu[k].key) romate(k,0);
}
}
}
void del(int &k,int x)
{
if(!k) return;
if(shu[k].val==x)
{
// shu[k].num1--;shu[k].num--;
if(shu[k].num1>1) shu[k].num1--,shu[k].num--;
else
{
if(shu[k].ch[0]==0||shu[k].ch[1]==0)
{
k=shu[k].ch[0]+shu[k].ch[1];
return;
}
int d=shu[shu[k].ch[0]].key<shu[shu[k].ch[1]].key;
romate(k,d);
del(k,x);//只到把这个点沉到最底部
up(k);
}
}
else shu[k].num--,del(shu[k].ch[shu[k].val<x],x);
}
int find(int &k,int x)
{
// cout<<"zhi="<<shu[k].val<<endl;
if(!k) return 0;
if(shu[k].val==x) return shu[shu[k].ch[0]].num;
else if(shu[k].val<x) return find(shu[k].ch[1],x)+shu[k].num1+shu[shu[k].ch[0]].num;
else
{
return find(shu[k].ch[0],x);
}
}
int rankk(int &k,int x)
{
// if(!k) return 0;
// if(x>shu[shu[k].ch[0]].num&&x<=shu[shu[k].ch[0]].num+shu[k].num1) return shu[k].val;
if(shu[shu[k].ch[0]].num>=x)
{
return rankk(shu[k].ch[0],x);
}
else if(x>shu[k].num1+shu[shu[k].ch[0]].num)
{
return rankk(shu[k].ch[1],x-shu[k].num1-shu[shu[k].ch[0]].num);
}
else return shu[k].val;
}
int pre(int &k,int x)
{
if(!k) return -1e8;
if(x<=shu[k].val) return pre(shu[k].ch[0],x);
return max(shu[k].val,pre(shu[k].ch[1],x));
}
int nex(int &k,int x)
{
if(!k) return 1e8;
if(x>=shu[k].val) return nex(shu[k].ch[1],x);
return min(shu[k].val,nex(shu[k].ch[0],x));
}
int main()
{
cin>>n;
int root=0;
for(int i=1;i<=n;i++)
{
// cout<<"kkk="<<i<<endl;
int num,zhi;
cin>>num>>zhi;
if(num==1) insert(root,zhi);
else if(num==2) del(root,zhi);
else if(num==3) cout<<find(root,zhi)+1<<endl;
else if(num==4) cout<<rankk(root,zhi)<<endl;
else if(num==5) cout<<pre(root,zhi)<<endl;
else cout<<nex(root,zhi)<<endl;
// cout<<"ans="<<ans<<endl;
}
}
普通平衡树:可以实现求插入,删除,求排名,求第k大,前驱,后继。
然而这并没什么卵用,因为树状数组或者线段树也能实现这些而且代码编写更简单。。。。