#include<cstdio>
class SGT {
public:
SGT() : root(NIL), del_num(0) { }
void insert(int key) {
if(root == NIL) root = newNode(key);
int now = root;
while(true) {
++node[now].size;
if(key < node[now].key) {
if(node[now].left == NIL) {
node[now].left = newNode(key);
}
now = node[now].left;
} else if(node[now].key < key) {
if(node[now].right == NIL) {
node[now].right = newNode(key);
}
now = node[now].right;
} else {
++node[now].cnt;
break;
}
}
int *son = &root;
while(node[*son].key != key) {
if(!balance(*son)) {
rebuild(son);
break;
}
if(key < node[*son].key) {
son = &node[*son].left;
} else if(node[*son].key < key) {
son = &node[*son].right;
}
}
return;
}
int getKth(int k) {
int now = root;
while(1) {
int left = 0;
if(node[now].left != NIL) left = node[node[now].left].size;
if(k <= left) {
now = node[now].left;
} else if(k <= left + node[now].cnt) {
break;
} else {
k -= left;
k -= node[now].cnt;
now = node[now].right;
}
}
return node[now].key;
}
void remove(int key) {
int now = root;
while(true) {
--node[now].size;
if(key < node[now].key) {
now = node[now].left;
} else if(node[now].key < key) {
now = node[now].right;
} else {
--node[now].cnt;
if(node[now].cnt == 0) {
++del_num;
}
break;
}
}
if((del_num << 1) > node[root].size) {
rebuild(&root);
}
return;
}
int getRank(int key) {
int now = root;
int res = 1;
while(true) {
if(now == NIL || node[now].key == key) {
if(now != NIL && node[now].left != NIL) {
res += node[node[now].left].size;
}
break;
} else if(node[now].key < key) {
res += node[now].cnt;
if(node[now].left != NIL) {
res += node[node[now].left].size;
}
now = node[now].right;
} else if(key < node[now].key) {
now = node[now].left;
}
}
return res;
}
private:
int root;
struct Node {
Node() : key(0), left(NIL), right(NIL), cnt(0), size(0) { }
int key;
int cnt;
int size;
int left;
int right;
};
bool balance(int key) {
return (node[key].left == NIL ||
node[key].size * BALANCE_SIZE >= (double)node[node[key].left].size) &&
(node[key].right == NIL ||
node[key].size * BALANCE_SIZE >= (double)node[node[key].right].size);
}
int newNode(int key) {
static int cnt = -1;
++cnt;
node[cnt].key = key;
return cnt;
}
void recycle(int now, int &cnt, int *id) {
if(node[now].left != NIL) recycle(node[now].left, cnt, id);
if(node[now].cnt > 0) {
id[++cnt] = now;
} else {
--del_num;
}
if(node[now].right != NIL) recycle(node[now].right, cnt, id);
return;
}
int build(const int *arr, int left, int right) {//[left, right]
const int mid = left + right >> 1;
node[arr[mid]].size = node[arr[mid]].cnt;
if(mid - 1 >= left) {
node[arr[mid]].left = build(arr, left, mid - 1);
node[arr[mid]].size += node[node[arr[mid]].left].size;
} else {
node[arr[mid]].left = NIL;
}
if(mid + 1 <= right) {
node[arr[mid]].right = build(arr, mid + 1, right);
node[arr[mid]].size += node[node[arr[mid]].right].size;
} else {
node[arr[mid]].right = NIL;
}
return arr[mid];
}
void rebuild(int *son) {
int now = *son;
int len = 0;
static int *id = new int[MAX_SGT_NODE_NUM];
recycle(now, len, id);
*son = build(id, 1, len);
return;
}
static const int NIL;
static const double BALANCE_SIZE;
static const int MAX_SGT_NODE_NUM;
static Node* node;
int del_num;
};
const int SGT::MAX_SGT_NODE_NUM = 100000 + 10;
SGT::Node *SGT::node = new SGT::Node[MAX_SGT_NODE_NUM];
const int SGT::NIL = -1;
const double SGT::BALANCE_SIZE = 0.75;
int main() {
SGT sgt;
int num;
scanf("%d", &num);
while(num--) {
int ope;
int key;
scanf("%d%d", &ope, &key);
switch(ope) {
case 1: {
sgt.insert(key);
break;
}
case 2: {
sgt.remove(key);
break;
}
case 3: {
printf("%d\n", sgt.getRank(key));
break;
}
case 4: {
printf("%d\n", sgt.getKth(key));
break;
}
case 5: {
printf("%d\n", sgt.getKth(sgt.getRank(key) - 1));
break;
}
case 6: {
printf("%d\n", sgt.getKth(sgt.getRank(key + 1)));
break;
}
}
}
return 0;
}
SGT
Share