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