一、题目:
二、思路:
用树状数组实现的平衡树,实现起来很简单,但有很多细节需要考虑。
维护一个权值树状数组,查排名时直接前缀和,前驱、后继都很简单。比较难的是已知排名求值,需要倍增。
怎么能写二分呢?倍增比二分快几百倍。——LSH
需要离散化,而细节很多,具体看代码。
三、代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read(void){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return f*x;
}
const int maxn=100005;
int n,b[maxn],cnt;
struct Opt{
int opt,x;
}q[maxn];
struct BIT{
int tree[maxn];
inline int lowbit(int x){return x&(-x);}
inline void add(int p,int x){
while(p<=cnt){
tree[p]+=x;
p+=lowbit(p);
}
}
inline int rank(int p){
int ans=1;--p;
while(p>0){
ans+=tree[p];
p-=lowbit(p);
}
return ans;
}
inline int val(int rank){
int ans=0,Cnt=0;
for(register int i=20;i>=0;--i){
ans+=(1<<i);
if(ans>cnt||Cnt+tree[ans]>=rank)ans-=(1<<i);
else Cnt+=tree[ans];
}
return ++ans;
}
inline int pre(int x){
return val(rank(x)-1);
}
inline int nxt(int x){
return val(rank(x+1));
}
}T;
int main(){
n=read();
for(register int i=1;i<=n;++i){
q[i].opt=read();
q[i].x=read();
if(q[i].opt!=4)b[++cnt]=q[i].x;
}
sort(b+1,b+cnt+1);
cnt=unique(b+1,b+cnt+1)-b-1;
for(register int i=1;i<=n;++i){
if(q[i].opt!=4)q[i].x=lower_bound(b+1,b+cnt+1,q[i].x)-b;
}
for(register int i=1;i<=n;++i){
switch(q[i].opt){
case 1:
T.add(q[i].x,1);
break;
case 2:
T.add(q[i].x,-1);
break;
case 3:
cout<<T.rank(q[i].x)<<endl;
break;
case 4:
// T.add(q[i].x,1);
cout<<b[T.val(q[i].x)]<<endl;
// T.add(q[i].x,-1);
break;
case 5:
T.add(q[i].x,1);
cout<<b[T.pre(q[i].x)]<<endl;
T.add(q[i].x,-1);
break;
case 6:
T.add(q[i].x,1);
cout<<b[T.nxt(q[i].x)]<<endl;
T.add(q[i].x,-1);
break;
}
}
system("pause");
return 0;
}