#include using namespace std; mt19937 rng_priority; struct node { int l, r; int x, y; int cnt; node (const int x_) : x(x_), y(rng_priority()), l(-1), r(-1), cnt(1) {} // node (const int x_) // { // x = x_; // y = rng_priority(); // l = -1; // r = -1; // cnt = 1; // } }; struct treap_manager { vector pool; int subtree (const int v) const { return v == -1 ? 0 : pool[v].cnt; } void recalc (const int v) { if (v != -1) pool[v].cnt = subtree(pool[v].l) + 1 + subtree(pool[v].r); } int add_node(const int x) { const int ans = int(pool.size()); pool.push_back(node(x)); return ans; } int merge(int l, int m, int r) { return merge(merge(l, m), r); } pair split (const int t, const int xs) { if (t == -1) return pair(-1, -1); int l, r; if (pool[t].x < xs) { /// Так МОЖНО написать, но не нужно. // const int mem = pool[t].r; // pool[t].r = -1; // tie(l, r) = split(mem, x); // pool[t].r = l; tie(l, r) = split(pool[t].r, xs); pool[t].r = l; recalc(t); return pair(t, r); } else { // pool[t].x >= x; tie(l, r) = split(pool[t].l, xs); pool[t].l = r; recalc(t); return pair(l, t); } } int merge (int l, int r) { if (l == -1) return r; if (r == -1) return l; if (pool[l].y > pool[r].y) { pool[l].r = merge(pool[l].r, r); recalc(l); return l; } else { pool[r].l = merge(l, pool[r].l); recalc(r); return r; } } /// добавить вершину ver в дерево tree int insert_node (const int tree, const int ver) { int l, r; tie(l, r) = split(tree, pool[ver].x); return merge(l, ver, r); } int insert_key (const int tree, const int x) { const int ver = add_node(x); return insert_node(tree, ver); } /// возвращает идентификатор дерева после удаления ключа x int remove_key (const int tree, const int x) { int l, m, r; tie(l, m) = split(tree, x); /// в l все ключи < x /// в m все ключи >= x tie(m, r) = split(m, x + 1); /// в m теперь ключ x return merge(l, r); } /// найти k-тый по возрастанию ключ в поддереве root и вернуть его int get_kth_key (const int root, const int k) { assert(0 <= k && k < subtree(root)); if (k == subtree(pool[root].l)) return pool[root].x; if (k < subtree(pool[root].l)) return get_kth_key(pool[root].l, k); /// k >= subtree(pool[root].l) + 1; /// от 0 до subtree(root) - subtree(pool[root].l) - 1 == subtree(pool[root].r); return get_kth_key(pool[root].r, k - subtree(pool[root].l) - 1); } void print_keys (ostream &cout, const int root) { if (root == -1) return; print_keys(cout, pool[root].l); cout << pool[root].x << ' '; print_keys(cout, pool[root].r); } }; int main() { int n; cin >> n; treap_manager treap; int cnt_vertices = 0, root = -1; for (int i = 0; i < n; i++) { int t, k; cin >> t >> k; cnt_vertices += t; if (t == +1) root = treap.insert_key(root, k); else if (t == -1) root = treap.remove_key(root, k); else if (t == 0) { k--; /// [0, cnt_vertices) -> [0, cnt_vertices) развёрнутый cout << treap.get_kth_key(root, treap.subtree(root) - k - 1) << '\n'; } // treap.print_keys(cerr, root); // cerr << endl; } return 0; }