#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
#include <climits>
#include <stack>
using namespace std;
typedef int ElemType;
typedef struct BNode
{
bool is_leaf;
int size;
std::vector<ElemType>key;
std::vector<BNode*>child;
}BNode;
typedef struct search_return
{
BNode* node;
int k;
}search_return;
class BTree
{
public:
BNode* root;
int t;
private:
void split_child(BNode* R,int k);
int merge_child(BNode* R, int k);
int fix_child(BNode* R, int index);
ElemType node_delete(BNode* T, unsigned index);
unsigned node_Insert(BNode* T, ElemType x);
unsigned find_index(BNode* T, ElemType x);
int node_num(BNode* T);
public:
BTree(int degree);
search_return search(ElemType x);
void insert(ElemType x);
void eraser(ElemType x);
int node_rank(ElemType x);
ElemType search_rank(int rank);
ElemType prev_node(ElemType x);
ElemType next_node(ElemType x);
void traverse();
};
BTree::BTree(int degree)
{
root = new BNode;
root->size = 0;
root->is_leaf = true;
t = degree;
}
void BTree::split_child(BNode* R, int k)
{
BNode* p = R->child[k];
BNode* lNode = new BNode;
BNode* rNode = new BNode;
lNode->is_leaf = p->is_leaf;
lNode->size = this->t - 1;
rNode->is_leaf = p->is_leaf;
rNode->size = this->t - 1;
for (int i = 0; i < t - 1; ++i)
lNode->key.push_back(p->key[i]);
int mid_key = p->key[t-1];
for (int i = t; i < 2*t - 1; ++i)
rNode->key.push_back(p->key[i]);
if (!p->is_leaf)
{
for (int i = 0; i < t; ++i)
lNode->child.push_back(p->child[i]);
for (int i = t; i < 2 * t; ++i)
rNode->child.push_back(p->child[i]);
}
R->key.push_back(mid_key);
sort(R->key.begin(), R->key.end());
++R->size;
R->child[k] = lNode;
int n = R->child.size();
R->child.push_back(R->child[n - 1]);
for (int i = n - 1; i >= k + 2; --i)
R->child[i] = R->child[i - 1];
R->child[k + 1] = rNode;
}
void BTree::insert(ElemType x)
{
if (root->size == 2 * t - 1)
{
BNode* new_root = new BNode;
new_root->size = 0;
new_root->is_leaf = false;
new_root->child.push_back(root);
root = new_root;
split_child(root, 0);
}
BNode* curr = root;
while (!curr->is_leaf)
{
int index = curr->size - 1;
while (index >= 0 && x < curr->key[index])
--index;
++index;
if (curr->child[index]->size == 2 * t - 1)
{
split_child(curr, index);
if (curr->key[index] < x)
++index;
}
curr = curr->child[index];
}
curr->key.push_back(x);
sort(curr->key.begin(), curr->key.end());
++curr->size;
}
int BTree::merge_child(BNode* R, int k)
{
BNode* lchild = R->child[k];
BNode* rchild = R->child[k + 1];
lchild->key.push_back(R->key[k]);
++lchild->size;
for (int i = 0; i < rchild->size; ++i)
lchild->key.push_back(rchild->key[i]);
lchild->size += rchild->size;
node_delete(R, k);
if(!rchild->is_leaf)
for (int i = 0; i <= rchild->size; ++i)
lchild->child.push_back(rchild->child[i]);
if (!R->size)
{
R = lchild;
return 2;
}
return 1;
}
int BTree::fix_child(BNode* R, int index)
{
BNode* kid = R->child[index];
if (kid->size < t)
{
BNode* lkid = R->child[index - 1];
BNode* rkid = R->child[index + 1];
if (index != 0 && lkid->size >= t)
{
node_Insert(kid, R->key[index - 1]);
if(!kid->is_leaf&&!lkid->is_leaf)
kid->child[0] = lkid->child[lkid->size];
R->key[index - 1] = node_delete(lkid, lkid->size - 1);
}
else if (index != R->size && rkid->size >= t)
{
node_Insert(kid, R->key[index]);
if (!kid->is_leaf && !rkid->is_leaf)
{
kid->child[kid->size] = rkid->child[0];
rkid->child[0] = rkid->child[1];
}
R->key[index] = node_delete(rkid, 0);
}
else if (index != 0)
return merge_child(kid, index - 1);
else
return merge_child(kid, index);
return 1;
}
return 0;
}
void BTree::eraser(ElemType x)
{
BNode* curr = root;
while (true)
{
unsigned index = find_index(curr, x);
if (index < curr->size && x == curr->key[index])
{
if (curr->is_leaf)
node_delete(curr, index);
else
{
BNode* lkid = curr->child[index];
BNode* rkid = curr->child[index + 1];
if (lkid->size >= t)
{
while (!lkid->is_leaf)
{
fix_child(lkid, lkid->size);
lkid = lkid->child[lkid->size];
}
curr->key[index] = node_delete(lkid, lkid->size - 1);
}
else if (rkid->size >= t)
{
while (!rkid->is_leaf)
{
fix_child(rkid, 0);
rkid = rkid->child[0];
}
curr->key[index] = node_delete(rkid, 0);
}
else
{
merge_child(curr, index);
curr = curr->child[index];
continue;
}
}
return;
}
else
{
if (curr->is_leaf)
{
std::cout << "no exit!\n";
return;
}
int judge = fix_child(curr, index);
if (judge == 2)
curr = root;
else
curr = curr->child[find_index(curr, x)];
}
}
}
void BTree::traverse()
{
std::queue<BNode*>Q;
Q.push(root);
while (!Q.empty())
{
BNode* tp = Q.front();
Q.pop();
for (int i = 0; i < tp->size; ++i)
std::cout << tp->key[i] << ' ';
std::cout << std::endl;
int n = tp->child.size();
if(!tp->is_leaf)
for (int i = 0; i < n; ++i)
Q.push(tp->child[i]);
}
}
ElemType BTree::node_delete(BNode* T, unsigned index)
{
ElemType re = T->key[index];
--T->size;
while (index < T->size)
{
T->key[index] = T->key[index + 1];
if (!T->is_leaf)
T->child[index + 1] = T->child[index + 2];
++index;
}
T->key.pop_back();
if (!T->is_leaf)
T->child.pop_back();
return re;
}
unsigned BTree::node_Insert(BNode* T, ElemType x)
{
int index = T->size;
T->key.push_back(0);
if(!T->is_leaf)
T->child.push_back(NULL);
while (index > 0 && x < T->key[index - 1])
{
T->key[index] = T->key[index - 1];
if(!T->is_leaf)
T->child[index + 1] = T->child[index];
--index;
}
if(!T->is_leaf)
T->child[index + 1] = T->child[index];
T->key[index] = x;
++T->size;
return index;
}
unsigned BTree::find_index(BNode* T, ElemType x)
{
unsigned i = 0;
while (i < T->size && T->key[i] < x)
++i;
return i;
}
int BTree::node_num(BNode* T)
{
int re = T->size;
if(!T->is_leaf)
for (int i = 0; i <= T->size; ++i)
re += node_num(T->child[i]);
return re;
}
int BTree::node_rank(ElemType x)
{
int rank = 0;
BNode* curr = root;
while (true)
{
int index = find_index(curr, x);
if (index != curr->size && x == curr->key[index])
{
if (!curr->is_leaf)
for (int i = 0; i <= index; ++i)
rank += node_num(curr->child[i]);
rank += (index + 1);
return rank;
}
else
{
rank += index;
if (!curr->is_leaf)
{
for (int i = 0; i < index; ++i)
rank += node_num(curr->child[i]);
curr = curr->child[index];
}
else
return 0;
}
}
return rank;
}
ElemType BTree::search_rank(int rank)
{
BNode* curr = root;
int curr_rank = 0;
while (true)
{
if (!curr->is_leaf)
{
for (int i = 0; i <= curr->size; ++i)
{
int temp_rank = rank;
temp_rank += node_num(curr->child[i]);
++temp_rank;
if (temp_rank == rank)
return curr->key[i];
else if (temp_rank > rank)
curr = curr->child[i];
else
curr_rank = temp_rank;
}
}
else
{
for (int i = 0; i < curr->size; ++i)
{
++curr_rank;
if (curr_rank == rank)
return curr->key[i];
}
}
}
return INT_MAX;
}
ElemType BTree::prev_node(ElemType x)
{
ElemType ans = INT_MIN;
std::queue<BNode*>Q;
Q.push(root);
while (!Q.empty())
{
BNode* tp = Q.front();
Q.pop();
int index = find_index(tp, x);
for (int i = 0; i < index; ++i)
if (tp->key[i]<x && tp->key[i]>ans)
ans = tp->key[i];
if(!tp->is_leaf)
Q.push(tp->child[index]);
}
return ans;
}
ElemType BTree::next_node(ElemType x)
{
ElemType ans = INT_MAX;
std::queue<BNode*>Q;
Q.push(root);
while (!Q.empty())
{
BNode* tp = Q.front();
Q.pop();
int index = find_index(tp, x);
for (int i = index; i < tp->size; ++i)
if (tp->key[i]>x && tp->key[i]<ans)
ans = tp->key[i];
if (!tp->is_leaf)
{
if (index != tp->size && tp->key[index] == x)
Q.push(tp->child[index + 1]);
else
Q.push(tp->child[index]);
}
}
return ans;
}
int main()
{
int n;
cin >> n;
BTree my_tree(20);
while (n--)
{
int choice, x;
cin >> choice >> x;
switch (choice)
{
case 1:
my_tree.insert(x);
break;
case 2:
my_tree.eraser(x);
break;
case 3:
cout << my_tree.node_rank(x) << endl;
break;
case 4:
cout << my_tree.search_rank(x) << endl;
break;
case 5:
cout << my_tree.prev_node(x) << endl;
break;
case 6:
cout << my_tree.next_node(x) << endl;
break;
default:
break;
}
}
return 0;
}