#include <bits/stdc++.h>
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<node> 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<int, int> split (const int t, const int xs)
	{
		if (t == -1)
			return pair<int, int>(-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<int, int>(t, r);
		}
		else
		{
//			pool[t].x >= x;

			tie(l, r) = split(pool[t].l, xs);
			pool[t].l = r;
			recalc(t);
			return pair<int, int>(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;
}