Cod sursa(job #1752281)

Utilizator stefanzzzStefan Popa stefanzzz Data 3 septembrie 2016 13:52:32
Problema Zeap Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.86 kb
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <ctime>
#include <cassert>
#define MAXL 1000
#define INF 0x3f3f3f3f
using namespace std;

char s[MAXL];

class Treap {
    struct Node {
        Node *left, *right;
        int key, pr, sz, minDif, minVal, maxVal;

        Node(Node *left, Node *right, int key) {
            this -> left = left;
            this -> right = right;
            this -> key = this -> minVal = this -> maxVal = key;
            this -> sz = 1;
            this -> minDif = INF;
            this -> pr = (rand() << 16) ^ rand();
        }

        ~Node() {
            if(left) delete left;
            if(right) delete right;
        }

        void recalc() {
            minVal = maxVal = key;
            minDif = INF;
            sz = 1;

            if(left) {
                minVal = left -> minVal;
                minDif = min(left -> minDif, key - (left -> maxVal));
                sz += left -> sz;
            }
            if(right) {
                maxVal = right -> maxVal;
                minDif = min(minDif, min(right -> minDif, (right -> minVal) - key));
                sz += right -> sz;
            }
        }
    };

public:
    Node *root;

    Treap() {
        srand(time(0));
        root = NULL;
    }

    ~Treap() {
        delete root;
    }

    Node* merge(Node *left, Node *right) {
        if(!left) return right;
        if(!right) return left;

        if(left -> pr > right -> pr) {
            left -> right = merge(left -> right, right);
            left -> recalc();
            return left;
        }
        else {
            right -> left = merge(right -> left, left);
            right -> recalc();
            return right;
        }
    }

    void split(Node* node, int x, Node* &left, Node* &right) {
        left = right = NULL;
        if(node == NULL) return;

        if(x <= node -> key) {
            split(node -> left, x, left, node -> left);
            right = node;
        }
        else {
            split(node -> right, x, node -> right, right);
            left = node;
        }

        node -> recalc();
    }

    bool hasKey(Node *node, int key) {
        if(node == NULL) return 0;

        if(key == node -> key) return 1;
        if(key < node -> key) return hasKey(node -> left, key);
        return hasKey(node -> right, key);
    }

    void insert(int key) {
        if(hasKey(root, key)) return;

        Node *left, *right;
        split(root, key, left, right);
        root = merge(merge(left, new Node(NULL, NULL, key)), right);
    }

    bool remove(int key) {
        if(!hasKey(root, key)) return 0;

        Node *left, *mid, *right;
        split(root, key, left, right);
        split(right, key + 1, mid, right);

        assert(mid != NULL && mid -> key == key && mid ->sz == 1);
        delete mid;

        root = merge(left, right);
        return 1;
    }

    int getSize() {
        return root ? (root -> sz) : 0;
    }
};

int main() {
    freopen("zeap.in", "r", stdin);
    freopen("zeap.out", "w", stdout);
    Treap t;

    while(fgets(s, MAXL, stdin) != NULL) {
        string q = string(s);

        if(q.substr(0, 3) == "MAX") {
            printf("%d\n", (t.getSize() < 2) ? (-1) : ((t.root -> maxVal) - (t.root -> minVal)));
        }
        else if(q.substr(0, 3) == "MIN") {
            printf("%d\n", (t.getSize() < 2) ? (-1) : (t.root -> minDif));
        }
        else {
            int x = atoi(q.substr(1).c_str());

            switch(q[0]) {
                case 'I':
                    t.insert(x); break;
                case 'S':
                    if(t.remove(x) == 0)
                        printf("-1\n");
                    break;
                case 'C':
                    printf("%d\n", (t.hasKey(t.root, x) ? 1 : 0));
                    break;
                default:
                    assert(0);
            }
        }
    }

    return 0;
}