#include <cstdio>
#include <cassert>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <functional>
#include <stack>
#include <queue>
#include <tuple>
#include <type_traits>
#define getchar getchar_unlocked
#define putchar putchar_unlocked
#define _rep(_1, _2, _3, _4, name, ...) name
#define rep2(i, n) rep3(i, 0, n)
#define rep3(i, a, b) rep4(i, a, b, 1)
#define rep4(i, a, b, c) for (int i = int(a); i < int(b); i += int(c))
#define rep(...) _rep(__VA_ARGS__, rep4, rep3, rep2, _)(__VA_ARGS__)
using namespace std;
using i64 = long long;
using u8 = unsigned char;
using u32 = unsigned;
using u64 = unsigned long long;
using f80 = long double;
int get_int() {
int c, n;
while ((c = getchar()) < '0');
n = c - '0';
while ((c = getchar()) >= '0') n = n * 10 + (c - '0');
return n;
}
const int BUFF_SIZE = 1 << 19;
template <typename val_t>
class IntegralTrie {
static_assert(is_integral<val_t>::value);
public:
IntegralTrie() : stacksize(0) {}
void insert(val_t value) { insert(root, value, W); }
void erase(val_t value) { erase(root, value, W); }
bool find(val_t value) const { return find(root, value, W); }
private:
static constexpr int W = sizeof(val_t) * 8;
static constexpr int B = 4;
struct Node {
int son[1 << B];
int active;
void reset() { active = 0; fill(son, son + (1 << B), -1); }
Node() { reset(); }
} root, buff[BUFF_SIZE];
int stk[BUFF_SIZE];
int stacksize;
inline int alloc() {
static int ptr;
int pos = stacksize > 0 ? stk[--stacksize] : ptr++;
buff[pos].reset();
return pos;
}
inline void dealloc(int pos) {
stk[stacksize++] = pos;
}
static inline int shift(val_t value, int R) {
return (R > B ? ((value >> (R - B)) & ((1 << B) - 1)) :
(value & ((1 << R) - 1)));
}
void insert(Node& n, val_t value, int R) {
const int l = shift(value, R);
n.active |= 1 << l;
if (R > B) {
if (n.son[l] == -1) n.son[l] = alloc();
insert(buff[n.son[l]], value, R - B);
}
}
void erase(Node& n, val_t value, int R) {
const int l = shift(value, R);
if (~n.active >> l & 1) {
return;
}
if (R > B) {
erase(buff[n.son[l]], value, R - B);
if (buff[n.son[l]].active == 0) {
dealloc(n.son[l]);
n.son[l] = -1;
n.active &= ~(1 << l);
}
} else n.active &= ~(1 << l);
}
bool find(const Node& n, val_t value, int R) const {
const int l = shift(value, R);
if (~n.active >> l & 1) {
return false;
}
if (R > B) return find(buff[n.son[l]], value, R - B);
return true;
}
};
void solve() {
#ifdef INFOARENA
freopen("hashuri.in", "r", stdin);
freopen("hashuri.out", "w", stdout);
#endif
IntegralTrie<u32> t;
int Q = get_int();
rep(_, Q) {
int type = get_int(); u32 x = get_int();
if (type == 1) {
t.insert(x);
} else if (type == 2) {
t.erase(x);
} else {
printf("%d\n", t.find(x));
}
}
}
int main() {
clock_t beg = clock();
solve();
clock_t end = clock();
fprintf(stderr, "%.3f sec\n", double(end - beg) / CLOCKS_PER_SEC);
return 0;
}