Description
现在已有N个整数,你有以下三种操作:
1.表示加入一个值为A的整数
2.表示删除其中值为B的整数
3.表示输出这些整数中第K小的数
Input
第一行,两个整数N,M,表示最开始有N个整数,总共有M个操作
第二行用空格隔开的N个整数
接下来M行,每行表示一个操作
Output
若干行,一行一个整数,表示所求的第K小的数字
Sample Input
5 5
6 2 7 4 9
1 8
1 6
3 10
2 4
3 3
Sample Output
0
7
Hint
注意:如果有多个大小相同的数字,只把他们看做一个数字,如样例。
若找不到第K小的数,输出0
数据范围:
0<=N<=2,000,000
M<=1,000,000
-1,000,000,000<=每个整数<=1,000,000,000
【分析】
没有什么好说的,一个裸的平衡树求第k小数。这里给出SBT实现的完整代码,注意一些细节的处理。
【代码】
/*
ID:Ciocio
LANG:C++
DATE:2013-11-22
TASK:K-th Number
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define MAXN 2000005
struct SBTnode{
int lc,rc,sz,key;
}T[MAXN<<1];
int N,M,root,SBTtot;
void _read(int &x,bool mark=false)
{
char tt;
for(;tt=getchar(),tt<'0'||'9'<tt;) if(tt=='-') mark=1;
for(x=0;'0'<=tt&&tt<='9';x=x*10+tt-'0',tt=getchar());
x=mark?-x:x;
}
void _Right_Rotate(int &x)
{
int k=T[x].lc;
T[x].lc=T[k].rc;
T[k].rc=x;
T[k].sz=T[x].sz;
T[x].sz=T[T[x].lc].sz+T[T[x].rc].sz+1;
x=k;
}
void _Left_Rotate(int &x)
{
int k=T[x].rc;
T[x].rc=T[k].lc;
T[k].lc=x;
T[k].sz=T[x].sz;
T[x].sz=T[T[x].lc].sz+T[T[x].rc].sz+1;
x=k;
}
void _Maintain(int &x,bool flag)
{
if(flag)
{
if(T[T[T[x].rc].rc].sz>T[T[x].lc].sz)
_Left_Rotate(x);
else if(T[T[T[x].rc].lc].sz>T[T[x].lc].sz)
_Right_Rotate(T[x].rc),_Left_Rotate(x);
else return;
}
else
{
if(T[T[T[x].lc].lc].sz>T[T[x].rc].sz)
_Right_Rotate(x);
else if(T[T[T[x].lc].rc].sz>T[T[x].rc].sz)
_Left_Rotate(T[x].lc),_Right_Rotate(x);
else return;
}
_Maintain(T[x].lc,0);
_Maintain(T[x].rc,1);
_Maintain(x,0);
_Maintain(x,1);
}
void _Insert(int &x,int key)
{
if(!x)
{
x=++SBTtot;
T[x].key=key;
T[x].sz=1;
T[x].lc=T[x].rc=0;
return;
}
T[x].sz++;
if(key<T[x].key)
_Insert(T[x].lc,key);
else
_Insert(T[x].rc,key);
_Maintain(x,key>=T[x].key);
}
int _Search(int x,int key)
{
if(key==T[x].key||x==0) return x;
if(key>T[x].key) return _Search(T[x].rc,key);
else return _Search(T[x].lc,key);
}
int _Maximum(int x)
{
while(T[x].rc)
x=T[x].rc;
return T[x].key;
}
void _Delete(int &x,int key)
{
T[x].sz--;
if(key==T[x].key)
{
if((!T[x].lc)||(!T[x].rc))
x=T[x].lc+T[x].rc;
else
{
int Max=_Maximum(T[x].lc);
T[x].key=Max;
_Delete(T[x].lc,Max);
}
}
else if(key<T[x].key)
_Delete(T[x].lc,key);
else
_Delete(T[x].rc,key);
_Maintain(x,0);
_Maintain(x,1);
}
int _Select(int x,int k)
{
while(x)
{
if(k<=T[T[x].lc].sz)
x=T[x].lc;
else if(k>T[T[x].lc].sz+1)
{
k-=T[T[x].lc].sz+1;
x=T[x].rc;
}
else
return T[x].key;
}
return -1;
}
void _init()
{
_read(N);_read(M);
for(int i=1;i<=N;i++)
{
int a;_read(a);
if(!_Search(root,a))
_Insert(root,a);
}
}
void _solve()
{
int p,a;
for(int i=1;i<=M;i++)
{
_read(p);_read(a);
if(p==1&&(!_Search(root,a)))
_Insert(root,a);
else if(p==2&&_Search(root,a))
_Delete(root,a);
else if(p==3)
{
int ans=_Select(root,a);
printf("%d\n",ans==-1?0:ans);
}
}
}
int main()
{
_init();
_solve();
return 0;
}