// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;



template <typename T>

class avl_tree {

	struct node {

		T val;

		int dep, size;

		node *ch[2];

		node() : node(0) {}

		node(T v, node* l = nullptr, node* r = nullptr)

			: val(v), dep(1), size(1), ch{ l, r } {}

		void *operator new(size_t) {

			static const int pmax = 2e5;

			static int p = 0;

			static node pool[pmax];

			return pool + p++;

		}

	};

	int depth(node *t) { return !t ? 0 : t->dep; }

	int count(node *t) { return !t ? 0 : t->size; }

	node *update(node *t) {

		t->dep = max(depth(t->ch[0]), depth(t->ch[1])) + 1;

		t->size = count(t->ch[0]) + count(t->ch[1]) + 1;

		return t;

	}

	node *rotate(node *t, int b) {

		node *s = t->ch[!b];

		t->ch[!b] = s->ch[b];

		s->ch[b] = t;

		update(t);

		return update(s);

	}

	node *fix(node *t) {

		if (!t) return t;

		int dd = depth(t->ch[0]) - depth(t->ch[1]);

		if (abs(dd) < 2) return t;

		int b = dd < 0;

		if (depth(t->ch[b]->ch[!b]) > depth(t->ch[b]->ch[b])) {

			t->ch[b] = rotate(t->ch[b], b);

		}

		return rotate(t, !b);

	}

	node *insert(node *t, T val) {

		if (!t) return new node(val);

		if (val == t->val) return t;

		int b = val > t->val;

		t->ch[b] = insert(t->ch[b], val);

		return fix(update(t));

	}

	T minimum(node *t) {

		while (t->ch[0]) t = t->ch[0];

		return t->val;

	}

	node *erase(node *t) {

		if (!t) return t;

		if (!t->ch[0] && !t->ch[1]) return nullptr;

		if (!t->ch[0]) return t->ch[1];

		if (!t->ch[1]) return t->ch[0];

		T mini = minimum(t->ch[1]);

		return fix(update(new node(mini, t->ch[0], erase(t->ch[1], mini))));

	}

	node *erase(node *t, T val) {

		if (!t) return t;

		if (val == t->val) return fix(erase(t));

		int b = val > t->val;

		t->ch[b] = erase(t->ch[b], val);

		return fix(update(t));

	}

	node *root;

public:

	avl_tree() : root(nullptr) {}

	int size() {

		return count(root);

	}

	void insert(T val) {

		root = insert(root, val);

	}

	void erase(T val) {

		root = erase(root, val);

	}

	bool count(T val) {

		node *t = root;

		while (t) {

			if (t->val == val) return true;

			t = t->ch[val > t->val];

		}

		return false;

	}

};



int main()

{

	ios::sync_with_stdio(false), cin.tie(0);

	int q;

	cin >> q;

	avl_tree<int> avl;

	while (q--) {

		int com, x;

		cin >> com >> x;

		if (com == 0) {

			avl.insert(x);

			printf("%d\n", avl.size());

		}

		else if (com == 1) {

			puts(avl.count(x) ? "1" : "0");

		}

		else {

			avl.erase(x);

		}

	}

	return 0;

}




// Faster C++ solution for the same problem (measured speedup: 1.3015022553344695x):
#include <bits/stdc++.h>

using namespace std;



template <typename T>

class avl_tree {

	struct node {

		T val;

		int dep;

		node *ch[2];

		node() : node(0) {}

		node(T v, node* l = nullptr, node* r = nullptr)

			: val(v), dep(1), ch{ l, r } {}

		void *operator new(size_t) {

			static const int pmax = 2e5; // number of nodes

			static int p = 0;

			static node pool[pmax];

			return pool + p++;

		}

	};

	int depth(node *t) { return !t ? 0 : t->dep; }

	node *update(node *t) {

		t->dep = max(depth(t->ch[0]), depth(t->ch[1])) + 1;

		return t;

	}

	node *rotate(node *t, int b) {

		node *s = t->ch[!b];

		t->ch[!b] = s->ch[b];

		s->ch[b] = t;

		update(t);

		return update(s);

	}

	node *fix(node *t) {

		if (!t) return t;

		int dd = depth(t->ch[0]) - depth(t->ch[1]);

		if (abs(dd) < 2) return t;

		int b = dd < 0;

		if (depth(t->ch[b]->ch[!b]) > depth(t->ch[b]->ch[b])) {

			t->ch[b] = rotate(t->ch[b], b);

		}

		return rotate(t, !b);

	}

	node *insert(node *t, T val) {

		if (!t) {

			++cnt;

			return new node(val);

		}

		if (val == t->val) return t;

		int b = val > t->val;

		t->ch[b] = insert(t->ch[b], val);

		return fix(update(t));

	}

	T minimum(node *t) {

		while (t->ch[0]) t = t->ch[0];

		return t->val;

	}

	node *erase(node *t) {

		if (!t) return t;

		if (!t->ch[0]) return t->ch[1];

		if (!t->ch[1]) return t->ch[0];

		T mini = minimum(t->ch[1]);

		++cnt;

		return fix(update(new node(mini, t->ch[0], erase(t->ch[1], mini))));

	}

	node *erase(node *t, T val) {

		if (!t) return t;

		if (val == t->val) {

			--cnt;

			return fix(erase(t));

		}

		int b = val > t->val;

		t->ch[b] = erase(t->ch[b], val);

		return fix(update(t));

	}

	node *root;

	int cnt;

public:

	avl_tree() : root(nullptr), cnt(0) {}

	int size() {

		return cnt;

	}

	void insert(T val) {

		root = insert(root, val);

	}

	void erase(T val) {

		root = erase(root, val);

	}

	bool count(T val) {

		node *t = root;

		while (t) {

			if (t->val == val) return true;

			t = t->ch[val > t->val];

		}

		return false;

	}

};



int main()

{

	int q;

	scanf("%d", &q);

	avl_tree<int> st;

	while (q--) {

		int t, x;

		scanf("%d%d", &t, &x);

		switch (t) {

		case 0:

			st.insert(x);

			printf("%d\n", st.size());

			break;

		case 1:

			printf("%d\n", st.count(x));

			break;

		default:

			st.erase(x);

		}

	}

	return 0;

}