#include <bits/stdc++.h>
using namespace std;
const int kMin = 0;
const int kMax = 2e9 + 1;
class CuteTree {
struct Node { int val, l, r; };
vector<Node> T = {{kMax + 1, 0, 0}};
int root = 0;
int insert(int cur, int b, int e, int upd) {
if (cur == 0) return upd;
if (T[cur].val == T[upd].val) return cur;
if (T[upd].val < T[cur].val)
swap(T[upd].val, T[cur].val);
int m = b + (e - b) / 2;
if (T[upd].val <= m) {
T[cur].l = insert(T[cur].l, b, m, upd);
} else {
T[cur].r = insert(T[cur].r, m + 1, e, upd);
}
return cur;
}
int pop(int node) {
if (T[node].l == 0 && T[node].r == 0) return 0;
if (T[T[node].l].val > T[T[node].r].val) {
swap(T[node].val, T[T[node].r].val);
T[node].r = pop(T[node].r);
} else {
swap(T[node].val, T[T[node].l].val);
T[node].l = pop(T[node].l);
}
return node;
}
int erase(int node, int b, int e, int val) {
if (T[node].val > val) return node;
if (T[node].val == val) return pop(node);
int m = b + (e - b) / 2;
if (val <= m) T[node].l = erase(T[node].l, b, m, val);
else T[node].r = erase(T[node].r, m + 1, e, val);
return node;
}
int find(int node, int b, int e, int val) {
if (T[node].val > val) return 0;
if (T[node].val == val) return node;
int m = b + (e - b) / 2;
if (val <= m) return find(T[node].l, b, m, val);
else return find(T[node].r, m + 1, e, val);
}
public:
bool Contains(int val) {
return find(root, kMin, kMax, val) != 0;
}
void Erase(int val) {
root = erase(root, kMin, kMax, val);
}
void Insert(int val) {
T.push_back({val, 0, 0});
root = insert(root, kMin, kMax, T.size() - 1);
}
};
int main() {
ifstream cin("hashuri.in");
ofstream cout("hashuri.out");
ios_base::sync_with_stdio(false);
cin.tie(0);
CuteTree qt;
int n; cin >> n;
for (int i = 0; i < n; ++i) {
int t, x; cin >> t >> x;
if (t == 1) { qt.Insert(x); }
if (t == 2) { qt.Erase(x); }
if (t == 3) { cout << qt.Contains(x) << '\n'; }
}
}