题目大意:给你一些操作:
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 ",Treap.find(Treap.rt,x));else if(opt==4)printf("%d ",Treap.kth(Treap.rt,x));else if(opt==5){ int ans=-2000000000; Treap.pre(Treap.rt,x,ans); printf("%d ",ans); }else{ int ans=2000000000; Treap.nxt(Treap.rt,x,ans); printf("%d ",ans); } } return 0; }