Cod sursa(job #1981845)

Utilizator cosmin.pascaruPascaru Cosmin cosmin.pascaru Data 17 mai 2017 00:14:01
Problema Zeap Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.04 kb
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <fstream>

using namespace std;

#define INF ((int)2e9)

struct Treap{
    Treap *left, *right;

    int key;
    int priority;

    int size;
    int min_dif;

    int min_elem;
    int max_elem;

    Treap(int key){
        this->key = key;
        this->priority = rand();

        this->size = 1;
        this->max_elem = key;
        this->min_elem = key;

        this->min_dif = INF;

        this->left = nullptr;
        this->right = nullptr;
    }
};

void update(Treap* root){
    if (root == nullptr){
        return;
    }

    root->size = 1;
    root->min_dif = INF;

    root->min_elem = root->key;
    root->max_elem = root->key;

    if (root->left != nullptr){
        root->size += root->left->size;

        root->min_elem = root->left->min_elem;

        root->min_dif = min(root->min_dif, root->left->min_dif);
        root->min_dif = min(root->min_dif, root->key - root->left->max_elem);
    }

    if (root->right != nullptr){
        root->size += root->right->size;
        root->max_elem = root->right->max_elem;

        root->min_dif = min(root->min_dif, root->right
                ->min_dif);
        root->min_dif = min(root->min_dif, root->right->min_elem - root->key);
    }
}

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

void merge(Treap *& root, Treap *left, Treap *right){
    if (left == nullptr || right == nullptr){
        root = (left != nullptr) ? left : right;
    }
    else if (left->priority > right->priority){
        merge(left->right, left->right, right);
        root = left;
    }
    else{
        merge(right->left, left, right->left);
        root = right;
    }
    update(root);
}

void insert(Treap *&root, Treap *elem){
    if (root == nullptr){
        root = elem;
    }
    else if (elem->priority > root->priority){
        split(root, elem->key, elem->left, elem->right);
        root = elem;
    }
    else if (elem->key < root->key){
        insert(root->left, elem);
    }
    else{
        insert(root->right, elem);
    }

    update(root);
}

int erase(Treap *& root, int key){
    int ret;

    if (root == nullptr){
        ret = -1;
    }
    else if (root->key == key){
//        Treap *to_delete = root;
        merge(root, root->left, root->right);
//        delete to_delete;
        ret = 1;
    }
    else if (key < root->key){
        ret = erase(root->left, key);
    }
    else{
        ret = erase(root->right, key);
    }

    update(root);

    return ret;
}

int search(Treap *root, int val){
    if (root == nullptr){
        return 0;
    }

    if (root->key == val){
        return 1;
    }

    if (val < root->key){
        return search(root->left, val);
    }
    return search(root->right, val);
}

int main() {

    ifstream cin("zeap.in");
    ofstream cout("zeap.out");

    srand(time(0));

    Treap* root = nullptr;

    char op[5];
    while (cin >> op){

        int k;

        switch (op[0]){
            case 'I':
                cin >> k;
                insert(root, new Treap(k));
                break;

            case 'S':
                cin >> k;
                if (erase(root, k) == -1){
                    cout << -1 << '\n';
                };
                break;

            case 'C':
                cin >> k;
                cout << search(root, k) << '\n';
                break;

            case 'M':
                switch (op[1]){
                    case 'I':
                        cout << (root->min_dif == INF ? -1 : root->min_dif) << '\n';
                        break;

                    case 'A':
                        cout << ((root->max_elem - root->min_elem == 0) ? -1 : (root->max_elem - root->min_elem)) << '\n';
                        break;
                }
                break;
        }
    }
    return 0;
}