#include <fstream>
#include <algorithm>
using namespace std;
ifstream fin("hashuri.in");
ofstream fout("hashuri.out");
struct AVL
{
int key, h;
AVL *lt, *rt;
};
AVL *root;
void get_h(AVL *nod)
{
nod->h = 1;
if (nod->lt != NULL)
nod->h = nod->lt->h;
if (nod->rt != NULL)
nod->h = max(nod->h, nod->rt->h);
}
void rotate_lt(AVL *nod, AVL *father)
{
bool l = false;
if (father->lt == nod)
l = true;
AVL *aux = nod->rt;
nod->rt = aux->lt;
aux->lt = nod;
//nod = aux;
if (root == nod)
root = aux;
else if (l == true)
father->lt = aux;
else
father->rt = aux;
get_h(nod);
get_h(aux);
}
void rotate_rt(AVL *nod, AVL *father)
{
bool l = false;
if (father->lt == nod)
l = true;
AVL *aux = nod->lt;
nod->lt = aux->rt;
aux->rt = nod;
//nod = aux;
if (root == nod)
root = aux;
else if (l == true)
father->lt = aux;
else
father->rt = aux;
get_h(nod);
get_h(aux);
}
void balance(AVL *nod, AVL *father)
{
if (nod->lt != NULL)
{
if (nod->rt != NULL)
{
if (nod->lt->h - nod->rt->h > 1)
{
if (nod->lt->rt != NULL)
{
if (nod->lt->lt != NULL)
{
if (nod->lt->rt->h - nod->lt->lt->h > 1)
rotate_lt(nod->lt, nod);
}
else
rotate_lt(nod->lt, nod);
}
rotate_rt(nod, father);
}
else if (nod->rt->h - nod->lt->h > 1)
{
if (nod->rt->lt != NULL)
{
if (nod->rt->rt != NULL)
{
if (nod->rt->lt->h - nod->rt->rt->h > 1)
rotate_rt(nod->rt, nod);
}
else
rotate_rt(nod->rt, nod);
}
rotate_lt(nod, father);
}
}
else
{
if (nod->lt->h > 1)
{
if (nod->lt->rt != NULL)
{
if (nod->lt->lt != NULL)
{
if (nod->lt->rt->h - nod->lt->lt->h > 1)
rotate_lt(nod->lt, nod);
}
else
rotate_lt(nod->lt, nod);
}
rotate_rt(nod, father);
}
}
}
else if (nod->rt != NULL)
{
if (nod->rt->h > 1)
{
if (nod->rt->lt != NULL)
{
if (nod->rt->rt != NULL)
{
if (nod->rt->lt->h - nod->rt->rt->h > 1)
rotate_rt(nod->rt, nod);
}
else
rotate_rt(nod->rt, nod);
}
rotate_lt(nod, father);
}
}
}
void add(AVL *&nod, int val, AVL *father)
{
if (nod == NULL)
{
AVL *aux = new AVL;
aux->key = val;
aux->h = 1;
aux->lt = NULL;
aux->rt = NULL;
nod = aux;
return;
}
if (val < nod->key)
add(nod->lt, val, nod);
else
add(nod->rt, val, nod);
nod->h = 1;
if (nod->lt != NULL)
nod->h = nod->lt->h + 1;
if (nod->rt != NULL)
nod->h = max(nod->h, nod->rt->h + 1);
if (nod->lt != NULL)
{
if (nod->rt != NULL)
{
if (abs(nod->lt->h - nod->rt->h) > 1)
balance(nod, father);
}
else
{
if (nod->lt->h > 1)
balance(nod, father);
}
}
else if (nod->rt != NULL)
{
if (nod->rt->h > 1)
balance(nod, father);
}
}
void del_balance(AVL *nod, AVL *nodL, AVL *father)
{
if (nod == nodL)
return;
if (nod == NULL)
return;
if (nodL->key < nod->key)
del_balance(nod->lt, nodL, nod);
else
del_balance(nod->rt, nodL, nod);
nod->h = 1;
if (nod->lt != NULL)
nod->h = nod->lt->h + 1;
if (nod->rt != NULL)
nod->h = max(nod->h, nod->rt->h + 1);
if (nod->lt != NULL)
{
if (nod->rt != NULL)
{
if (abs(nod->lt->h - nod->rt->h) > 1)
balance(nod, father);
}
else
{
if (nod->lt->h > 1)
balance(nod, father);
}
}
else if (nod->rt != NULL)
{
if (nod->rt->h > 1)
balance(nod, father);
}
}
void delRad()
{
AVL *now = root, *nodInit = root;
if (now->lt != NULL) // are fiu stang
{
now = now->lt;
if (now->rt == NULL)
{
root = now;
root->rt = nodInit->rt;
//nod->lt = now->lt;
del_balance(root, now, root);
delete nodInit;
return;
}
while (now->rt->rt != NULL)
now = now->rt;
root = now->rt;
now->rt = now->rt->lt;
root->lt = nodInit->lt;
root->rt = nodInit->rt;
//nod->lt = now->rt;
//now->rt = now->rt->lt;
//nod->lt->lt = nodInit->lt;
del_balance(root, now, root);
delete nodInit;
return;
}
else if (now->rt != NULL) // are fiu drept
{
now = now->rt;
if (now->lt == NULL)
{
root = now;
//nod->lt = now->rt;
del_balance(root, now, root);
delete nodInit;
return;
}
while (now->lt->lt != NULL)
now = now->lt;
root = now->lt;
now->lt = now->lt->rt;
root->rt = nodInit->rt;
//nod->lt = now->lt;
//now->lt = now->lt->rt;
//nod->lt->rt = nodInit->rt;
del_balance(root, now, root);
delete nodInit;
return;
}
else // e frunza
{
del_balance(root, now, root);
delete nodInit;
root = NULL;
// nod->lt = NULL;
return;
}
}
void del(AVL *nod, int x)
{
if (nod == NULL)
return;
if (nod->key == x) // sterg radacina
{
delRad();
return;
}
if (nod->lt != NULL && nod->lt->key == x)
{
AVL *now = nod->lt, *nodInit = nod->lt;
if (now->lt != NULL) // are fiu stang
{
now = now->lt;
if (now->rt == NULL)
{
nod->lt = now;
nod->lt->rt = nodInit->rt;
del_balance(root, now, root);
delete nodInit;
return;
}
while (now->rt->rt != NULL)
now = now->rt;
nod->lt = now->rt;
now->rt = now->rt->lt;
nod->lt->lt = nodInit->lt;
nod->lt->rt = nodInit->rt;
del_balance(root, now, root);
delete nodInit;
return;
}
else if (now->rt != NULL) // are fiu drept
{
now = now->rt;
if (now->lt == NULL)
{
nod->lt = now;
del_balance(root, now, root);
delete nodInit;
return;
}
while (now->lt->lt != NULL)
now = now->lt;
nod->lt = now->lt;
now->lt = now->lt->rt;
nod->lt->rt = nodInit->rt;
del_balance(root, now, root);
delete nodInit;
return;
}
else // e frunza
{
del_balance(root, now, root);
delete nodInit;
nod->lt = NULL;
return;
}
}
else if (nod->rt != NULL && nod->rt->key == x)
{
AVL *now = nod->rt, *nodInit = nod->rt;
if (now->lt != NULL) // are fiu stang
{
now = now->lt;
if (now->rt == NULL)
{
nod->rt = now;
nod->rt->rt = nodInit->rt;
del_balance(root, now, root);
delete nodInit;
return;
}
while (now->rt->rt != NULL)
now = now->rt;
nod->rt = now->rt;
now->rt = now->rt->lt;
nod->rt->lt = nodInit->lt;
nod->rt->rt = nodInit->rt;
del_balance(root, now, root);
delete nodInit;
return;
}
else if (now->rt != NULL) // are fiu drept
{
now = now->rt;
if (now->lt == NULL)
{
nod->rt = now;
del_balance(root, now, root);
delete nodInit;
return;
}
while (now->lt->lt != NULL)
now = now->lt;
nod->rt = now->lt;
now->lt = now->lt->rt;
nod->rt->rt = nodInit->rt;
del_balance(root, now, root);
delete nodInit;
return;
}
else // e frunza
{
del_balance(root, now, root);
delete nodInit;
nod->rt = NULL;
return;
}
}
if (x < nod->key)
del(nod->lt, x);
else
del(nod->rt, x);
}
int findX(AVL *nod, int x)
{
if (nod == NULL)
return 0;
if (nod->key == x)
return 1;
if (x < nod->key)
findX(nod->lt, x);
else
findX(nod->rt, x);
}
int main()
{
int N;
fin >> N;
for (int i = 1, x, op; i <= N; ++i)
{
fin >> op >> x;
if (op == 1)
{
if (!findX(root, x))
add(root, x, root);
}
else if (op == 2)
{
if (findX(root, x))
del(root, x);
}
else
fout << findX(root, x) << '\n';
}
fin.close();
fout.close();
return 0;
}