//operatii de determinare a cheii precedente/succesoare cheii curente
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <set>
#include <cstdlib>
#include <ctime>
using namespace std;
typedef multiset <int> setu;
setu S;
int maxdif = -1, mindif = -1;
/// Noduri in Treap: T1 - tipul cheilor (neaparat cu operatorii < , > definiti), T2 - tipul prioritatilor (neaparat numeric)
template <class T1, class T2> class Node {
public:
Node *left, *right, *parent;
T1 key;
T2 priority;
Node () { left = right = parent = NULL; }
Node (const T1 &k, const T2 &p) { left = right = parent = NULL, key = k, priority = p; }
pair<T1, T2> get_info() const { return make_pair(key, priority); }
};
/// Treap-ul (aceeasi observatie). Se observa ca am apelat membrii indirect (prin this->) pentru claritate unde e cazul (nu e tocmai necesar).
template <class T1, class T2> class Treap {
private:
vector< pair<T1, T2> > ino; /// vector cu parcurgerea in inordine
Node<T1, T2> *__mini (const Node<T1, T2> *x) const { /// minimul din subarborele x
while (x->left != NULL) x = x->left;
return (Node<T1, T2> *) x;
}
Node<T1, T2> *__maxi (const Node<T1, T2> *x) const { /// maximul din subarborele x
while (x->right != NULL) x = x->right;
return (Node<T1, T2> *) x;
}
void __make_ino(const Node<T1, T2> *x) { ///construieste parcurgerea in inordine a subarborelui x
if (x != NULL) {
__make_ino(x->left);
ino.push_back(make_pair(x->key, x->priority));
__make_ino(x->right);
}
}
void rotate_left(Node<T1, T2> *u) { /// !!! http://opendatastructures.org/ods-java/img3012.png
Node<T1, T2> *w = u->right;
w->parent = u->parent;
if (w->parent) {
if (w->parent->left == u) w->parent->left = w;
else w->parent->right = w;
}
u->right = w->left;
if (u->right != NULL) u->right->parent = u;
u->parent = w;
w->left = u;
if (u == this->root) {
this->root = w;
this->root->parent = NULL;
}
}
void rotate_right(Node<T1, T2> *u) {
Node<T1, T2> *w = u->left;
w->parent = u->parent;
if (w->parent != NULL) {
if (w->parent->left == u) w->parent->left = w;
else w->parent->right = w;
}
u->left = w->right;
if (u->left != NULL) u->left->parent = u;
u->parent = w;
w->right = u;
if (u == this->root) {
this->root = w;
this->root->parent = NULL;
}
}
void rotate_up(Node<T1, T2> *u) { /// rotiri in sus la inserari
while (u->parent && u->parent->priority > u->priority) {
if (u->parent->right == u) rotate_left(u->parent);
else rotate_right(u->parent);
}
if (!u->parent) this->root = u;
}
void rotate_down(Node<T1, T2> *u) { ///rotiri in jos la stergeri
while (u->left || u->right) {
if (u->left == NULL) rotate_left(u);
else if (u->right == NULL) rotate_right(u);
else if (u->left->priority < u->right->priority) rotate_right(u);
else rotate_left(u);
if (this->root == u) this->root = u->parent;
}
}
public:
/// trebuie sa accesam radacina in afara clasei (la unire si taiere de Treapuri)
Node<T1, T2> *root;
/// constructori
Treap () { root = NULL; }
Treap (const T1 &k, const T2 &p) { root = new Node<T1, T2>(k, p); }
Treap (const Node<T1, T2> *r) { root = new Node<T1, T2>(), *root = *r; } /// !!! COPIE ca sa nu stricam pointerul altui treap cand facem operatii cu acesta nou
/// metode tip query (ca la BST)
const Node<T1, T2> * mini () const { return __mini(root); }
const Node<T1, T2> * maxi () const { return __maxi(root); }
Node<T1, T2> * src (const int &k) const {
Node<T1, T2> *x = this->root;
while (x != NULL && k != x->key)
if (k < x->key) x = x->left;
else x = x->right;
return x;
}
static int min_key (Node<T1, T2> *nd) {
//Node<T1, T2> *x = this->root;
while (nd->left)
nd = nd->left;
return nd->key;
}
static int max_key (Node<T1, T2> *nd) {
//Node<T1, T2> *x = this->root;
while (nd->right)
nd = nd->right;
return nd->key;
}
int next_key(int x) {
Node<T1, T2> *s = src(x);
if (s->right)
return min_key(s->right);
Node<T1, T2> *pr = s->parent;
while (pr && s == pr->right) {
s = pr;
pr = pr->parent;
}
return pr->key;
}
int prev_key(int x) {
Node<T1, T2> *s = src(x);
if (s->left)
return max_key(s->left);
Node<T1, T2> *pr = s->parent;
while (pr && s == pr->left) {
s = pr;
pr = pr -> parent;
}
return pr -> key;
}
vector< pair<T1, T2> > get_ino() {
ino.clear();
__make_ino(this->root);
return ino;
}
/// metode tip update/delete
void ins(const T1 &k, const T2 &p) { ///insereaza (la fel ca la BST, doar ca mai face o rotatie la sfarsit)
Node<T1, T2> *x = root, *y = NULL, *z = new Node<T1, T2> (k, p);
while (x != NULL) {
y = x;
if (z->key < x->key) x = x->left;
else x = x->right;
}
z->parent = y;
if (!y) this->root = z;
else if (z->key < y->key) y->left = z;
else y->right = z;
rotate_up(z);
}
void del (Node<T1, T2> *z) { ///sterge un nod dat (il muta jos pana devine frunza, apoi se sterge)
rotate_down(z);
if (z->parent->left == z) z->parent->left = NULL;
else if (z->parent->right == z) z->parent->right = NULL;
delete(z);
}
///metode specifice (unire, taiere) - de apelat fara obiect de tip Treap
static pair<Treap *, Treap *> split(const T1 &k, const Treap<T1, T2> *tree) { ///separa treap-ul curent in doua treapuri, "first" din pereche are cheile mai mici decat k, celalalt mai mari.
pair<Treap *, Treap *> res;
if (k != tree->root->get_info().first) {
Treap<T1, T2> *dummy = new Treap<T1, T2>();///copie a Treap-ului curent... ATENTIE LA POINTERI COPIATI!
dummy->root = new Node<T1, T2>();
*(dummy->root) = *(tree->root);
dummy->ins(k, tree->root->priority - 1); ///...in care inseram un nod cu cheia data si prioritate mai mica decat minima (din radacina)
res = make_pair(new Treap<T1, T2>(dummy->root->left), new Treap<T1, T2>(dummy->root->right));
delete(dummy);
dummy = NULL;
}
else {
Treap<T1, T2> *l = new Treap<T1, T2>(tree->root->left), *r = new Treap<T1, T2>(tree->root);
delete (r->root->left);
r->root->left = NULL;
res = make_pair(l, r);
}
return res;
}
static Treap * join(const T1 &k, const Treap<T1, T2> *tree1, const Treap<T1, T2> *tree2) { ///uneste Treapul curent (this) avand cheile mai mici decat k cu unul "other" avand cheile mai mari decat k
Treap<T1, T2> *res = new Treap<T1, T2>(k, 0);
res->root->left = tree1->root;
res->root->right = tree2->root;
res->del(res->root);
return res;
}
};
typedef Treap<int, int> Trip;
typedef Node<int, int> Nod;
const int NMAX = 1000;
int __rand(int i) {
static bool flag = 1;
if (flag) {
srand(time(NULL));
flag = 0;
}
return rand() % i;
}
int main () {
ifstream cin("zeap.in");
ofstream cout("zeap.out");
Trip *tree = new Trip;
char lit;
int p = 1;
while (cin >> lit) {
if (lit == 'I') {
int x;
cin >> x;
Nod *s = tree->src(x);
if (!s) {
tree->ins(x, p);
if (x != Trip::min_key(tree->root))
S.insert(x - tree->prev_key(x));
if (x != Trip::max_key(tree->root))
S.insert(tree->next_key(x) - x);
++p;
}
}
else if (lit == 'S') {
int x;
cin >> x;
Nod *s = tree->src(x);
if (s) {
//cerr<<tree->prev_key(x) << " " << tree->next_key(x) << "\n";
int prv = 0, nxt = 0, p_n = 0;
if (x != Trip::min_key(tree->root))
prv = tree->prev_key(x);
if (x != Trip:: max_key(tree->root))
nxt = tree->next_key(x);
if (x != Trip::min_key(tree->root)) {
S.erase(x - prv);
if (x != Trip:: max_key(tree->root)) {
S.insert(nxt - prv);
p_n = 1;
}
}
if (x != Trip::max_key(tree->root)) {
S.erase(nxt - x);
if (x != Trip::min_key(tree->root) && !p_n)
S.insert(nxt - prv);
}
tree->del(s);
}
else
cout << "-1\n";
}
else if (lit == 'C') {
int x;
cin >> x;
Nod *s = tree->src(x);
if (s)
cout << "1\n";
else
cout << "0\n";
}
else {
cin >> lit;
if (lit == 'A') {
maxdif = Trip::max_key(tree->root) - Trip::min_key(tree->root);
cout << maxdif << "\n";
}
else {
setu :: iterator it = S.begin();
mindif = *it;
cout << mindif << "\n";
}
cin >> lit;
}
}
return 0;
}