http://www.spoj.com/problems/ORDERSET/
In this problem, you have to maintain a dynamic set of numbers which support the two fundamental operations
INSERT(S,x): if x is not in S, insert x into S
DELETE(S,x): if x is in S, delete x from S
and the two type of queries
K-TH(S) : return the k-th smallest element of S
COU“NT(S,x): return the number of elements of S smaller than x
//http://www.spoj.com/problems/ORDERSET/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int n,root,ans,Size,x,flag,pos;
const int maxm = 200000+10;
struct node{
int l,r,v,siz,rnd;
}tr[maxm];
char s[10];
void update(int &k){
tr[k].siz = tr[tr[k].l].siz+tr[tr[k].r].siz+1;
}
void lturn(int &k){
int tmp = tr[k].r;
tr[k].r = tr[tmp].l;
tr[tmp].l = k;
tr[tmp].siz = tr[k].siz;
update(k);
k = tmp;
}
void rturn(int &k){
int tmp = tr[k].l;
tr[k].l = tr[tmp].r;
tr[tmp].r = k;
tr[tmp].siz = tr[k].siz;
update(k);
k = tmp;
}
void tp_insert(int &k,int x){
if(k == 0){
flag = 1;
++Size;
k = ++pos;
tr[k].siz = 1;tr[k].v = x;tr[k].rnd = rand();
return;
}
if(tr[k].v == x) return;
else if(x > tr[k].v){
tp_insert(tr[k].r,x);if(flag) tr[k].siz++;
if(tr[tr[k].r].rnd < tr[k].rnd){
lturn(k);
}
}
else{
tp_insert(tr[k].l,x);if(flag) tr[k].siz++;
if(tr[tr[k].l].rnd < tr[k].rnd){
rturn(k);
//cout <<"flag = ="<<flag<<endl;
}
}
}
void tp_del(int &k,int x){
if(k == 0) return;
if(tr[k].v > x){
tp_del(tr[k].l,x);
if(flag) tr[k].siz--;
}
else if(tr[k].v < x){
tp_del(tr[k].r,x);
if(flag) tr[k].siz--;
}
else{
flag = 1;
if(tr[k].l*tr[k].r==0) k=tr[k].l+tr[k].r;
else if(tr[tr[k].l].rnd < tr[tr[k].r].rnd){//×ó±ßС£¬×óÉÏÈ¥£¬ÓÒÐý
rturn(k);
tp_del(k,x);
}
else{
lturn(k);
tp_del(k,x);
}
}
}
int tp_cnt(int &k,int x){
if(k == 0) return 0;
if(tr[k].v == x) return tr[tr[k].l].siz;
else if(x > tr[k].v){
return tr[tr[k].l].siz+1+tp_cnt(tr[k].r,x);
}
else return tp_cnt(tr[k].l,x);
}
int tp_numsmal(int &k,int x){
if(k == 0) return 0;
if(x <= tr[tr[k].l].siz){
return tp_numsmal(tr[k].l,x);
}
else if(x > tr[tr[k].l].siz + 1){
return tp_numsmal(tr[k].r,x-tr[tr[k].l].siz-1);
}
else return tr[k].v;
}
void print(int &k,int h){
if(tr[tr[k].r].siz != 0)
print(tr[k].r,h+1);
for(int i = 1; i <= h ; i++) printf(" ");
printf("%d(%d)\n",tr[k].v,tr[k].siz);
if(tr[tr[k].l].siz !=0)
print(tr[k].l,h+1);
}
void init(){
root= 0;
for(int i = 1; i <= n ; i++){
scanf("%s%d",s,&x);
if(s[0] == 'I'){
flag = 0;
tp_insert(root,x);
// printf("size = %d\n",Size);
// print(root,0);
}
if(s[0] == 'D'){
flag = 0;
tp_del(root,x);
if(flag) Size--;
// printf("size = %d\n",Size);
// print(root,0);
}
if(s[0] == 'C'){
cout <<tp_cnt(root,x)<<endl;
}
if(s[0] == 'K'){
if(x > Size){
cout <<"invalid"<<endl;
continue;
}
cout << tp_numsmal(root,x)<<endl;
}
}
}
int main(){
scanf("%d",&n);
init();
return 0;
}
/*
8
I -1
I -1
I 2
C 0
K 2
D -1
K 1
K 2
*/