题目大意:给你一些操作:
1.插入一个数;
2.删除一个数;
3.输出x是第几小的数;
4.输出第k小的数是几;
5.输出比x小的最大数;
6.输出比x大的最小数。
要你实现它。
解题思路:平衡树模板题。
用Treap/Splay/替罪羊树/pbds(雾)等均可。
我使用简单的Treap实现。
注意在5和6操作时,必须要搜到叶子才停止,否则会遗漏答案。
这里用指针实现,删除操作可能会出现内存浪费。
C++ Code:
#include<cstdio>
#include<cctype>
#include<ctime>
#include<cstdlib>
class treap{
private:
struct node{
node* ch[2];
int s,x,r,sz;
node(){
ch[0]=ch[1]=NULL;
}
};
void update(node*&o){
o->s=o->sz;
if(o->ch[0]!=NULL)o->s+=o->ch[0]->s;
if(o->ch[1]!=NULL)o->s+=o->ch[1]->s;
}
void rotate(node*& o,int d){
node* k=o->ch[d^1];
o->ch[d^1]=k->ch[d];
k->ch[d]=o;
update(o);
update(k);
o=k;
}
public:
node* rt;
void ins(node*&o,int p){
if(o==NULL){
o=new node;
o->s=o->sz=1;
o->x=p;
o->r=rand();
return;
}
if(p<o->x){
ins(o->ch[0],p);
if(o->ch[0]->r<o->r)rotate(o,1);
}else
if(p>o->x){
ins(o->ch[1],p);
if(o->ch[1]->r<o->r)rotate(o,0);
}else ++o->sz;
update(o);
}
void del(node*&o,int p){
if(o==NULL)return;
if(o->x==p){
if(o->sz>1)--o->sz;else
if(o->ch[0]==NULL&&o->ch[1]==NULL)o=NULL;else
if(o->ch[0]!=NULL&&o->ch[1]!=NULL){
if(o->ch[0]->r<o->ch[1]->r){
rotate(o,1);
del(o->ch[1],p);
}else{
rotate(o,0);
del(o->ch[0],p);
}
}else
if(o->ch[0]==NULL)o=o->ch[1];else o=o->ch[0];
if(o!=NULL)update(o);
}else{
if(p<o->x)del(o->ch[0],p);else del(o->ch[1],p);
if(o!=NULL)update(o);
}
}
int find(node* o,int p){
if(o==NULL)return 0;
int l=0;
if(o->ch[0]!=NULL)l=o->ch[0]->s;
if(o->x==p)return l+1;
if(o->x>p)return find(o->ch[0],p);
return l+o->sz+find(o->ch[1],p);
}
int kth(node* o,int k){
if(o==NULL)return 0;
int l=0;
if(o->ch[0]!=NULL)l=o->ch[0]->s;
if(k>l&&k<=l+o->sz)return o->x;
if(k<=l)return kth(o->ch[0],k);
return kth(o->ch[1],k-l-o->sz);
}
void pre(node* o,int p,int& ans){
if(o==NULL)return;
if(o->x<p){
if(ans<o->x)ans=o->x;
if(o->ch[1]!=NULL)pre(o->ch[1],p,ans);
}else
if(o->ch[0]!=NULL)pre(o->ch[0],p,ans);
}
void nxt(node* o,int p,int& ans){
if(o==NULL)return;
if(o->x>p){
if(ans>o->x)ans=o->x;
if(o->ch[0]!=NULL)nxt(o->ch[0],p,ans);
}else
if(o->ch[1]!=NULL)nxt(o->ch[1],p,ans);
}
treap(){rt=NULL;}
}Treap;
inline int readint(){
char c=getchar();
bool b=false;
for(;!isdigit(c);c=getchar())b=c=='-';
int d=0;
for(;isdigit(c);c=getchar())
d=(d<<3)+(d<<1)+(c^'0');
return b?-d:d;
}
int main(){
srand(2333);
for(int n=readint();n--;){
int opt=readint(),x=readint();
if(opt==1)Treap.ins(Treap.rt,x);else
if(opt==2)Treap.del(Treap.rt,x);else
if(opt==3)printf("%d\n",Treap.find(Treap.rt,x));else
if(opt==4)printf("%d\n",Treap.kth(Treap.rt,x));else
if(opt==5){
int ans=-2000000000;
Treap.pre(Treap.rt,x,ans);
printf("%d\n",ans);
}else{
int ans=2000000000;
Treap.nxt(Treap.rt,x,ans);
printf("%d\n",ans);
}
}
return 0;
}