For a set $S$ of integers, perform a sequence of the following operations. Note that each value in $S$ must be unique.

* insert($x$): Insert $x$ to $S$ and report the number of elements in $S$ after the operation.
* find($x$): Report the number of $x$ in $S$ (0 or 1).
* delete($x$): Delete $x$ from $S$.

Constraints

* $1 \leq q \leq 200,000$
* $0 \leq x \leq 1,000,000,000$

Input

The input is given in the following format.


$q$
$query_1$
$query_2$
:
$query_q$


Each query $query_i$ is given by


0 $x$


or


1 $x$


or


2 $x$


where the first digits 0, 1 and 2 represent insert, find and delete operations respectively.

Output

For each insert operation, print the number of elements in $S$.
For each find operation, print the number of specified elements in $S$.

Example

Input

8
0 1
0 2
0 3
2 2
1 1
1 2
1 3
0 2


Output

1
2
3
1
0
1
3
#include <bits/stdc++.h>
using namespace std;

template <typename T = int, const T U = (T)1 << (T)30>
class van_emde_boas_tree {

	const T ctz;

	struct node {
		T min, max;
		node *summary;
		unordered_map<T, node*> cluster;
		node() : min(U), max(-1), summary(nullptr) {}
	} *root;

	int cnt;

private:

	T downsqrt(T ub) const {
		return ub >> (T)1;
	}

	T upsqrt(T ub) const {
		return (ub + 1) >> (T)1;
	}

	T high(T x, T ub) const {
		return x >> downsqrt(ub);
	}

	T low(T x, T ub) const {
		return x & (((T)1 << downsqrt(ub)) - 1);
	}

	T index(T x, T y, T ub) const {
		return (x << downsqrt(ub)) + y;
	}

	T minimum(node *v) const {
		return v ? v->min : U;
	}

	T maximum(node *v) const {
		return v ? v->max : -1;
	}

	bool member(node *v, T x, T ub) const {
		if (!v) return false;
		if (v->min == x || v->max == x) return true;
		if (v->cluster.empty()) return false;
		return member(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub));
	}

	node* empty_insert(node *v, T x, T ub) {
		if (!v) v = new node();
		v->min = v->max = x;
		return v;
	}

	node* insert(node *v, T x, T ub) {
		if (!v) v = new node();
		if (v->min == U) {
			empty_insert(v, x, ub);
			return v;
		}
		if (x < v->min) swap(x, v->min);
		if (ub > 1) {
			if (minimum(v->cluster[high(x, ub)]) == U) {
				v->summary = insert(v->summary, high(x, ub), upsqrt(ub));
				v->cluster[high(x, ub)] = empty_insert(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub));
			}
			else {
				v->cluster[high(x, ub)] = insert(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub));
			}
		}
		if (x > v->max) v->max = x;
		return v;
	}

	node* erase(node *v, T x, T ub) {
		if (v->min == v->max) {
			v->min = U;
			v->max = -1;
			return nullptr;
		}
		if (ub <= 1) {
			v->max = v->min = (x == 0);
			return v;
		}
		if (x == v->min) {
			T first_cluster = minimum(v->summary);
			v->min = x = index(first_cluster, minimum(v->cluster[first_cluster]), ub);
		}
		v->cluster[high(x, ub)] = erase(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub));
		if (minimum(v->cluster[high(x, ub)]) == U) {
			v->summary = erase(v->summary, high(x, ub), upsqrt(ub));
			if (x == v->max) {
				T summary_max = maximum(v->summary);
				if (summary_max == -1) {
					v->max = v->min;
				}
				else {
					v->max = index(summary_max, maximum(v->cluster[summary_max]), ub);
				}
			}
		}
		else if (x == v->max) {
			v->max = index(high(x, ub), maximum(v->cluster[high(x, ub)]), ub);
		}
		return v;
	}

	T successor(node *v, T x, T ub) const {
		if (!v) return U;
		if (ub <= 1) {
			if (x == 0 && v->max == 1) return 1;
			return U;
		}
		if (v->min != U && x < v->min) return v->min;
		T max_low = maximum(v->cluster[high(x, ub)]);
		if (max_low != -1 && low(x, ub) < max_low) {
			return index(high(x, ub), successor(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub)), ub);
		}
		T succ_cluster = successor(v->summary, high(x, ub), upsqrt(ub));
		if (succ_cluster == U) return U;
		return index(succ_cluster, minimum(v->cluster[succ_cluster]), ub);
	}

	T predecessor(node *v, T x, T ub) const {
		if (!v) return -1;
		if (ub <= 1) {
			if (x == 1 && v->min == 0) return 0;
			return -1;
		}
		if (v->max != -1 && x > v->max) return v->max;
		T min_low = minimum(v->cluster[high(x, ub)]);
		if (min_low != U && low(x, ub) > min_low) {
			return index(high(x, ub), predecessor(v->cluster[high(x, ub)], low(x, ub), downsqrt(ub)), ub);
		}
		T pred_cluster = predecessor(v->summary, high(x, ub), upsqrt(ub));
		if (pred_cluster == -1) {
			if (v->min != U && x > v->min) return v->min;
			return -1;
		}
		return index(pred_cluster, maximum(v->cluster[pred_cluster]), ub);
	}

	T get_ctz(T x) {
		T tmp = 1, res = 0;
		while (tmp < x) {
			tmp <<= (T)1;
			res++;
		}
		return res;
	}

public:

	van_emde_boas_tree() : ctz(get_ctz(U)), root(nullptr), cnt(0) {}

	int size() const {
		return cnt;
	}

	bool member(T x) const {
		return member(root, x, ctz);
	}

	T minimum() const {
		return minimum(root);
	}

	T maximum() const {
		return maximum(root);
	}

	void insert(T x) {
		if (!member(x)) root = insert(root, x, ctz), cnt++;
	}

	void erase(T x) {
		if (member(x)) root = erase(root, x, ctz), cnt--;
	}

	T successor(T x) const {
		return successor(root, x, ctz);
	}

	T predecessor(T x) const {
		return predecessor(root, x, ctz);
	}

};

int main()
{
	ios::sync_with_stdio(false), cin.tie(0);
	int q;
	cin >> q;
	van_emde_boas_tree<> veb;
	while (q--) {
		int com, x;
		cin >> com >> x;
		if (com == 0) {
			veb.insert(x);
			printf("%d\n", veb.size());
		}
		else if (com == 1) {
			puts(veb.member(x) ? "1" : "0");
		}
		else {
			veb.erase(x);
		}
	}
	return 0;
}

