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;

uint32_t xor128(){
	static uint32_t x = 123456789,y = 362436069,z = 521288629,w = 88675123;
	uint32_t t;
	t = x ^ (x << 11);
	x = y; y = z; z = w;
	return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
}

template<class T>
struct SkipListSSet{
	static const int MAX_HEIGHT = 100;
	struct Node{
		T x;
		int h;
		vector<Node*> nxt;
		Node(T x,int h) : x(x),h(h),nxt(h + 1){}
	};

	int h,n;
	Node *root;//,*stack[MAX_HEIGHT];

	SkipListSSet() : h(0),n(0){
		root = new Node(0,MAX_HEIGHT);
	}

	~SkipListSSet(){
		Node *u = root;
		while(u != NULL){
			Node *nxt = u->nxt[0];
			delete u;
			u = nxt;
		}
	}

	inline int pickHeight() const{ return __builtin_ctz(xor128()); }

	/*bool add(T x){
		Node *u = root;
		int r = h;
		while(r >= 0){
			while(u->nxt[r] != NULL && u->nxt[r]->x < x) u = u->nxt[r];
			if(u->nxt[r] != NULL && u->nxt[r]->x == x) return false; //already exists
			stack[r--] = u;
		}
		Node *w = new Node(x,pickHeight());
		while(h < w->h) stack[++h] = root;
		for(int i = 0;i <= w->h;i++){
			w->nxt[i] = stack[i]->nxt[i];
			stack[i]->nxt[i] = w;
		}
		n++;
		return true;
	}*/

	bool add(T x){
		Node *u = findPredNode(x);
		if(u->nxt[0] != NULL && u->nxt[0]->x == x) return false;
		Node *w = new Node(x,pickHeight());
		h = max(h,w->h);
		u = root;
		int r = h;
		while(r >= 0){
			while(u->nxt[r] != NULL && u->nxt[r]->x < x) u = u->nxt[r];
			if(r <= w->h){
				w->nxt[r] = u->nxt[r];
				u->nxt[r] = w;
			}
			r--;
		}
		n++;
		return true;
	}

	bool remove(T x){
		Node *u = root,*del = NULL;
		int r = h;
		while(r >= 0){
			while(u->nxt[r] != NULL && u->nxt[r]->x < x) u = u->nxt[r];
			if(u->nxt[r] != NULL && u->nxt[r]->x == x){
				del = u->nxt[r];
				u->nxt[r] = u->nxt[r]->nxt[r];
				if(u == root && u->nxt[r] == NULL) h--;
			}
			r--;
		}
		if(del != NULL){
			delete del;
			n--;
		}
		return (del != NULL);
	}

	Node* findPredNode(T x) const{
		Node *u = root;
		int r = h;
		while(r >= 0){
			while(u->nxt[r] != NULL && u->nxt[r]->x < x) u = u->nxt[r];
			r--;
		}
		return u;
	}

	T find(T x) const{
		Node *u = findPredNode(x);
		return (u->nxt[0] == NULL ? -1 : u->nxt[0]->x);
	}

	friend ostream &operator<<(ostream &os,const SkipListSSet &s){
		Node *u = s.root;
		os << '{';
		while(u->nxt[0] != NULL){
			u = u->nxt[0];
			os << u->x << ',';
		}
		return os << '}';
	}
};

signed main(){
	SkipListSSet<int> sset;
	int q;
	cin >> q;
	for(int i = 0;i < q;i++){
		int t,x;
		cin >> t >> x;
		if(t == 0){
			sset.add(x);
			cout << sset.n << endl;
		}else if(t == 1){
			cout << (sset.find(x) == x) << endl;
		}else{
			sset.remove(x);
		}
	}
}
