// Original C++ solution (slower):
#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;

}




// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>

using namespace std;



void compress(vector<int>& v) {

	auto vs = v;

	sort(vs.begin(), vs.end());

	vs.erase(unique(vs.begin(), vs.end()), vs.end());

	for (auto& val : v) {

		val = lower_bound(vs.begin(), vs.end(), val) - vs.begin();

	}

}



const int MAX = 2e5;



int main()

{

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

	int q;

	cin >> q;

	vector<int> c(q), x(q);

	for (int i = 0; i < q; i++) {

		cin >> c[i] >> x[i];

	}

	compress(x);

	vector<int> cnt(MAX);

	int size = 0;

	for (int i = 0; i < q; i++) {

		if (c[i] == 0) {

			if (!cnt[x[i]]) {

				cnt[x[i]] = 1;

				++size;

			}

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

		}

		else if (c[i] == 1) {

			puts(cnt[x[i]] ? "1" : "0");

		}

		else {

			if (cnt[x[i]]) {

				cnt[x[i]] = 0;

				--size;

			}

		}

	}

	return 0;

}




// Fastest known solution for this problem: