Cod sursa(job #1981359)

Utilizator valiro21Valentin Rosca valiro21 Data 15 mai 2017 14:57:43
Problema Zeap Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.04 kb
//
// Created by vrosca on 5/15/17.
//

#include <iostream>
#include <cstdlib>
#include <fstream>

using namespace std;

struct treap {
    treap *left, *right;
    int nr_elem, key, pri, min_delta, min, max;
};

void update (treap *root) {
    if (!root) return;

    root->nr_elem = (root->left ? root->left->nr_elem : 0) +
                    (root->right ? root->right->nr_elem : 0) +
                    1;

    root->min = root->key;
    if(root->left) root->min = min (root->min, root->left->key);
    if(root->right) root->min = min (root->min, root->right->key);

    root->max = root->key;
    if(root->left) root->max = max (root->max, root->left->key);
    if(root->right) root->max = max (root->max, root->right->key);

    // min delta
    root->min_delta = 999999999;
    root->max = root->key;
    if(root->left) {
        root->min_delta = min (root->min_delta, root->left->min_delta);
        root->min_delta = min (root->min_delta, root->key - root->left->max);
    }
    if(root->right) {
        root->min_delta = min (root->min_delta, root->right->min_delta);
        root->min_delta = min (root->min_delta, root->right->min - root->key);
    }
}

void split (treap *root, treap *& left, treap *& right, int key) {
    if (!root)
        left = right = nullptr;
    else if (key < root->key) {
        split (left, left, root->left, key);
        right = root;
    }
    else {
        split (right, root->right, right, key);
        left = root;
    }
    update (root);
}

void merge (treap *& root, treap *left, treap *right) {
    if (!left || !right) {
        root = left ? left : right;
    }
    else if (left->pri < right->pri) {
        merge (right->left, left, right->left);
        root = right;
    }
    else {
        merge (left->right, left->right, right);
        root = left;
    }
    update(root);
}

void insert_elem (treap *& root, treap *elem) {
    if (!root)
        root = elem;
    else if (root->pri < elem->pri) {
        split (root, elem->left, elem->right, elem->key);
        root = elem;
    }
    else if (elem->key < root->key)
        insert_elem (root->left, elem);
    else
        insert_elem (root->right, elem);
    update (root);
}

bool find (treap *root, int key) {
    if (!root) return false;

    if (root->key == key) return true;
    else if (root->key < key) return find (root->right, key);
    else return find (root->left, key);
}

void insert (treap *& root, int key) {
    treap *elem = new treap ();
    elem->left = elem->right = nullptr;
    elem->key = key;
    elem->pri = rand ();


    if (!find (root, key))
        insert_elem(root, elem);
}

void erase (treap *& root, int key) {
    if (!root) return;

    if (root->key == key) {
        treap *left = root->left, *right = root->right;
        delete root;
        merge (root, left, right);
    }
    else if (root->key < key) {
        erase(root->right, key);
    }
    else
        erase(root->left, key);
    update (root);
}

int getMaxDelta (treap *root) {
    if (!root || root->nr_elem < 2) return -1;
    int min = root->key;
    if (root->left) min = root->left->min;

    int max = root->key;
    if (root->right) max = root->right->max;

    return max - min;
}

int getMinDelta (treap *root) {
    if (!root || root->nr_elem < 2) return -1;
    return root->min_delta;
}

int main () {
    ifstream cin ("zeap.in");
    ofstream cout ("zeap.out");
    ios_base::sync_with_stdio(false);
    //cin.tie(0);
    srand (543254325);
    string s;
    treap * root = nullptr;

    while (cin >> s) {
        if (s == "MAX") {
            cout << getMaxDelta(root) << '\n';
        }
        else if (s == "MIN") {
            cout << getMinDelta(root) << '\n';
        }
        else {
            int x;
            cin >> x;
            if (s == "I") {
                insert(root, x);
            }
            else if (s == "S") {
                if (find (root, x))
                    erase (root, x);
                else
                    cout << "-1\n";
            }
            else {
                cout << find(root, x) << '\n';
            }
        }
    }

    return 0;
}