Cod sursa(job #1429378)

Utilizator mucenic_b101Bogdan Mucenic mucenic_b101 Data 6 mai 2015 11:27:06
Problema Zeap Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 10.04 kb
//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;
}