Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 6120 Solved: 2516
[Submit][Status][Discuss]
Description
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
Input
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
Output
对于操作3,4,5,6每行输出一个数,表示对应答案
Sample Input
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
Sample Output
106465
84185
492737
HINT
1.n的数据范围:n<=100000
2.每个数的数据范围:[-1e7,1e7]
Source
平衡树.
#include<cstdio>
#include<climits>
#include<cstdlib>
#include<iostream>
using namespace std;
#define INF INT_MAX/3*2
struct SplayTree{
struct Node{
Node *ch[2];
int r,v,s,size;
Node(int v,Node* nl):v(v){size=s=1;r=rand();ch[0]=ch[1]=nl;}
void maintain(){size=ch[0]->size+s+ch[1]->size;}
}*root,*null;
SplayTree(){
null=new Node(0,0);null->r=INT_MAX;null->size=null->s=0;
null->ch[0]=null->ch[1]=null;root=null;
}
void rotate(Node* &o,int d){
Node *k=o->ch[d];o->ch[d]=k->ch[d^1];k->ch[d^1]=o;
o->maintain();k->maintain();o=k;
}
void insert(Node* &o,int x){
if(o==null){o=new Node(x,null);return;}
if(o->v==x){o->s++,o->size++;return;}
insert(o->ch[x>o->v],x);
if(o->ch[x>o->v]->r<o->r) rotate(o,x>o->v);
else o->maintain();
}
void remove(Node* &o,int x){
if(o->v==x){
if(o->s>1){o->s--;o->size--;return;}
int d=o->ch[0]->r>o->ch[1]->r;
if(o->ch[d]==null){delete o;o=null;return;}
rotate(o,d);remove(o->ch[d^1],x);
}
else remove(o->ch[x>o->v],x);
o->maintain();
}
int kth(Node *o,int x){
int d=o->ch[0]->size;
if(x<=d) return kth(o->ch[0],x);
else if(x>d+o->s) return kth(o->ch[1],x-d-o->s);
return o->v;
}
int rank(Node *o,int x){
int d=o->ch[0]->size;
if(x<o->v) return rank(o->ch[0],x);
else if(x>o->v) return rank(o->ch[1],x)+d+o->s;
return d;
}
int prev(Node *o,int x){
if(o==null) return -INF;
if(x<=o->v) return prev(o->ch[0],x);
return max(o->v,prev(o->ch[1],x));
}
int next(Node* o,int x){
if(o==null) return INF;
if(x>=o->v) return next(o->ch[1],x);
return min(o->v,next(o->ch[0],x));
}
}T;
int main(){
srand('B'+'e'+'i'+'Y'+'u');
int n,opt,x;
scanf("%d",&n);
while(n--){
scanf("%d%d",&opt,&x);
switch(opt){
case 1:
T.insert(T.root,x);break;
case 2:
T.remove(T.root,x);break;
case 3:
printf("%d\n",T.rank(T.root,x)+1);break;
case 4:
printf("%d\n",T.kth(T.root,x));break;
case 5:
printf("%d\n",T.prev(T.root,x));break;
case 6:
printf("%d\n",T.next(T.root,x));break;
}
}
return 0;
}