#include <bits/stdc++.h>
using namespace std;
using LL = long long;

template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }


// std::vector Declaration
template<typename T>
vector<T> make_v(size_t a) { return vector<T>(a); }
template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts) {
   return vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}

// std::vector Initialization
template<typename T>
void fill_all(T& arr, const T& v) { arr = v; }
template<typename T, typename U>
void fill_all(T& arr, const U& v) { for (auto& i : arr) fill_all(i, v); }

// std::vector Debug
template<typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
   os << "[";
   bool a = 1;
   for (auto e : v ) {
      os << (a ? "" : " "); 
      os << e;
      a = 0;
   }
   os << "]";
   return os;
}

// std::pair Debug
template<typename T, typename U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {
   os << "(" << p.first << " " << p.second << ")";
   return os;
}

// std::set Debug
template<typename T>
ostream& operator<<(ostream& os, const set<T>& st) {
   os << "{";
   bool a = 1;
   for (auto e : st) {
      os << (a ? "" : " ");
      os << e;
      a = 0;
   }
   os << "}";
   return os;
}

// std::multiset Debug
template<typename T>
ostream& operator<<(ostream& os, const multiset<T>& st) {
   os << "{";
   bool a = 1;
   for (auto e : st) {
      os << (a ? "" : " ");
      os << e;
      a = 0;
   }
   os << "}";
   return os;
}

// std::map Debug
template<typename T, typename U>
ostream& operator<<(ostream& os, const map<T, U>& mp) {
   os << "{";
   bool a = 1;
   for (auto e : mp) {
      os << (a ? "" : " ");
      os << e.first << ":" << e.second;
      a = 0;
   }
   os << "}";
   return os;
}

// std::tuple Debug
template<int N, class Tuple>
void out(ostream& os, const Tuple& t){}
template<int N, class Tuple, class H, class ...Ts>
void out(ostream& os, const Tuple& t) {
   if (N) os << " ";
   os << get<N>(t);
   out<N+1,Tuple,Ts...>(os, t);
}
template<class ...Ts>
ostream& operator<<(ostream& os, const tuple<Ts...>& t) {
   os << "(";
   out<0,tuple<Ts...>,Ts...>(os, t);
   os << ")";
   return os;
}

// Debug
#define DUMP(x) cout<<#x<<" = "<<(x)<<endl


struct edge { int to, cost; };
ostream& operator<<(ostream& os, const edge& e) {
   os << "(" << e.to << ", " << e.cost << ")";
   return os;
}

const LL LINF = 1LL<<60;
const int IINF = 1<<30;
const LL MOD = 1e9+7;


mt19937 mt{ random_device{}() };
uniform_real_distribution<> dist(0, 1);

template<typename elem_t>
struct node_t
{
   using count_t = unsigned int;
   using pri_t = double;

   elem_t elem;
   node_t *lch, *rch, *par;
   count_t cnt;
   pri_t pri;

   node_t(elem_t elem) : elem(elem), lch(nullptr), rch(nullptr),
                         par(nullptr), cnt(1), pri((pri_t)dist(mt)) {}

   static count_t count(node_t* node) {
      // cout << "node_t::count is called" << endl;
      if (node != nullptr) {
         return node->cnt;
      } else {
         return 0;
      }
   }

   static node_t* update(node_t* node) {
      // cout << "node_t::update is called" << endl;
      assert(node != nullptr);
      node->cnt = count(node->lch) + count(node->rch) + 1;

      node->par = nullptr;
      if (node->lch != nullptr) {
         node->lch->par = node;
      }
      if (node->rch != nullptr) {
         node->rch->par = node;
      }

      return node;
   }

   static node_t* merge(node_t* l, node_t* r) {
      // cout << "node_t::merge is called" << endl;
      if (l == nullptr) {
         return r;
      } else if (r == nullptr) {
         return l;
      }

      assert(l->pri != r->pri);

      if (r->pri < l->pri) {
         l->rch = merge(l->rch, r);
         return update(l);
      } else {
         r->lch = merge(l, r->lch);
         return update(r);
      }
   }

   static pair<node_t*, node_t*> split(node_t* node, elem_t elem, bool includeToRight) {
      // cout << "node_t::split is called" << endl;
      if (node == nullptr) {
         return { nullptr, nullptr };
      }

      node_t *l, *r;
      if (includeToRight) {
         if (node->elem < elem) {
            tie(l, r) = split(node->rch, elem, includeToRight);
            node->rch = l;
            return { update(node), r };
         } else {
            tie(l, r) = split(node->lch, elem, includeToRight);
            node->lch = r;
            return { l, update(node) };
         }
      } else {
         if (node->elem <= elem) {
            tie(l, r) = split(node->rch, elem, includeToRight);
            node->rch = l;
            return { update(node), r };
         } else {
            tie(l, r) = split(node->lch, elem, includeToRight);
            node->lch = r;
            return { l, update(node) };
         }
      }
   }

   static node_t* insert(node_t* node, elem_t elem) {
      // cout << "nodt_t::insert is called" << endl;
      node_t *l, *c, *r;
      tie(c, r) = split(node, elem, false);
      tie(l, ignore) = split(c, elem, true);
      auto p_node = new node_t(elem);
      return merge(l, merge(p_node, r));
   }

   static pair<node_t*, node_t*> erase(node_t* node, elem_t elem) {
      // cout << "node_t::erase is called" << endl;
      node_t *l, *c, *r;
      tie(c, r) = split(node, elem, false);
      tie(l, ignore) = split(c, elem, true);
      return { merge(l, r), c };
   }

   static node_t* find(node_t* node, elem_t elem) {
      // cout << "node_t::find is called" << endl;
      if (node == nullptr) {
         return nullptr;
      }
      if (node->elem < elem) {
         return find(node->rch, elem);
      } else if (elem < node->elem) {
         return find(node->lch, elem);
      } else {
         return node;
      }
   }

   static node_t* at(node_t* node, count_t k) {
      assert(node != nullptr);
      assert(node->cnt > k);

      if (count(node->lch) == k) {
         return node;
      } else if (count(node->lch) > k) {
         return at(node->lch, k);
      } else {
         return at(node->rch, k-1-count(node->lch));
      }
   }

   static node_t* lower_bound(node_t* node, elem_t elem) {
      // cout << "node_t::lower_bound is called" << endl;
      if (node == nullptr) {
         return nullptr;
      }
      if (elem <= node->elem) {
         node_t* lb = lower_bound(node->lch, elem);
         if (lb != nullptr) {
            return lb;
         } else {
            return node;
         }
      } else {
         return lower_bound(node->rch, elem);
      }
   }

   node_t* next() {
      if (this->rch != nullptr) {
         node_t* t = this->rch;
         while (t->lch != nullptr) {
            t = t->lch;
         }
         return t;
      }
      node_t* t = this;
      while (t->par != nullptr && t->par->rch == t) {
         t = t->par;
      }
      return t->par;
   }

   static void show(node_t* node) {
      // cout << "node_t::show is called" << endl;
      if (node == nullptr) {
         return;
      }
      show(node->lch);
      cout << "node_t::show " << node
         << ", lch: " << node->lch
         << ", rch: " << node->rch
         << ", elem: " << node->elem
         << ", cnt: " << node->cnt
         << ", pri: " << node->pri << endl;
      show(node->rch);
   }
};



template<typename elem_t>
struct Treap
{
   using count_t = unsigned int;
   using pri_t = double;

   using node = node_t<elem_t>;
   node* root;

   Treap() : root(nullptr) {}

   count_t size() {
      return node::count(root);
   }

   void insert(elem_t elem) {
      root = node::insert(root, elem);
   }

   void erase(elem_t elem) {
      tie(root, ignore) = node::erase(root, elem);
   }

   node* find(elem_t elem) {
      return node::find(root, elem);
   }

   node* lower_bound(elem_t elem) {
      return node::lower_bound(root, elem);
   }

   node* at(count_t k) {
      return node::at(root, k);
   }

   node* begin() {
      return root;
   }

   void show() {
      node::show(root);
   }
};

int main()
{
   int q; cin >> q;

   vector<int> t(q), x(q);
   for (int i = 0; i < q; ++i) {
      cin >> t[i] >> x[i];
   }

   Treap<int> treap;

   for (int i = 0; i < q; ++i) {
      if (t[i] == 0) {
         treap.insert(x[i]);
         cout << treap.size() << endl;
      } else if (t[i] == 1) {
         cout << (treap.find(x[i]) ? 1 : 0) << endl;
      } else {
         treap.erase(x[i]);
      }
   }

   return 0;
}



Measured memory_bytes: 16876