Cod sursa(job #3133456)

Utilizator TheGodFather2131Alexandru Miclea TheGodFather2131 Data 25 mai 2023 18:22:55
Problema Zeap Scor 10
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 10.81 kb
//ALEXANDRU MICLEA

#include <vector>
#include <algorithm>
#include <string>
#include <cstring>
#include <queue>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <time.h>
#include <iomanip>
#include <deque>
#include <math.h>
#include <cmath>
#include <assert.h>
#include <stack>
#include <bitset>
#include <random>
#include <chrono>
#include <iostream>
#include <fstream>
#include <array>

using namespace std;



typedef long long ll;

//VARIABLES

const long long INF = 1e9 + 7;

class RBT {
private:
    struct node {
        int value;
        bool isBlack;

        node* left, * right, * dad;

        node(node* left, node* right, node* dad, int val = INF, bool isBlack = true) : value(val), isBlack(isBlack) {
            this->left = left;
            this->right = right;
            this->dad = dad;
        }
    };

    node* treeRoot, * NIL;

public:
    RBT() {
        treeRoot = new node(NULL, NULL, NULL);
        NIL = treeRoot;
    }

    node* search(int);
    int inTree(int);
    void leftRotate(node*);
    void rightRotate(node*);
    void insert(int);
    void remove(int);
    void transplant(node*, node*);
    int successor(int);
    int predecessor(int);
    int sorted(int, int);
    void insert_fix_up(node*);
    void remove_fix_up(node*);
    void redoRoot();
};

//FUNCTIONS

void RBT::rightRotate(node* root) {
    assert(root->left != NIL);
    node* swap = root->left;
    root->left = swap->right;
    if (swap->right != NIL) swap->right->dad = root;
    swap->dad = root->dad;
    if (root == root->dad->left) root->dad->left = swap;
    else root->dad->right = swap;
    swap->right = root;
    root->dad = swap;
}
void RBT::leftRotate(node* root) {
    assert(root->right != NIL);
    node* swap = root->right;
    root->right = swap->left;
    if (swap->left != NIL) swap->left->dad = root;
    swap->dad = root->dad;
    if (root->dad->left == root) root->dad->left = swap;
    else root->dad->right = swap;
    swap->left = root;
    root->dad = swap;
}
void RBT::insert(int val) {
    if (treeRoot == NIL) {
        treeRoot = new node(NIL, NIL, NIL, val, true);
    }
    else {
        node* pointer = treeRoot;
        while (true) {
            assert(pointer->value != val);
            if (pointer->value > val && pointer->left != NIL) {
                pointer = pointer->left;
                continue;
            }
            if (pointer->value < val && pointer->right != NIL) {
                pointer = pointer->right;
                continue;
            }

            break;
        }

        if (pointer->value < val) {
            pointer->right = new node(NIL, NIL, pointer, val, false);
            insert_fix_up(pointer->right);
        }
        if (pointer->value > val) {
            pointer->left = new node(NIL, NIL, pointer, val, false);
            insert_fix_up(pointer->left);
        }
    }
}
void RBT::redoRoot() {
    while (treeRoot->dad != NIL) {
        treeRoot = treeRoot->dad;
    }
    treeRoot->isBlack = true;
}
RBT::node* RBT::search(int val) {
    node* pointer = treeRoot;

    while (true) {
        if (pointer == NIL) return NIL;

        if (pointer->value == val) {
            return pointer;
        }
        if (pointer->value > val && pointer->left != NIL) {
            pointer = pointer->left;
            continue;
        }
        if (pointer->value < val && pointer->right != NIL) {
            pointer = pointer->right;
            continue;
        }
        return NIL;
    }
}
int RBT::inTree(int val) {
    node* pointer = search(val);
    if (pointer != NIL) return 1;
    return 0;
}
int RBT::predecessor(int val) {
    int ans = -(INF);

    node* pointer = treeRoot;

    while (pointer != NIL) {
        if (pointer->value <= val) {
            ans = max(ans, pointer->value);
            pointer = pointer->right;
        }
        else {
            pointer = pointer->left;
        }
    }

    return ans;
}
int RBT::successor(int val) {
    int ans = INF;

    node* pointer = treeRoot;

    while (pointer != NIL) {
        if (pointer->value >= val) {
            ans = min(ans, pointer->value);
            pointer = pointer->left;
        }
        else {
            pointer = pointer->right;
        }
    }

    return ans;
}
int RBT::sorted(int st, int dr) {

    int val;
    ll minn = INF;
    if (this->inTree(st)) val = st;
    else val = successor(st);

    while (val <= dr) {
        ll next = successor(val + 1);
        minn = min(minn, next - val);
        if (next == val) break;
        else val = next;
    }

    return minn;
}
void RBT::insert_fix_up(node* root) {
    while (root->dad->isBlack == false) {
        node* granddad = root->dad->dad;
        assert(granddad != NIL);

        if (root->dad == granddad->left) {
            if (granddad->right->isBlack == false) {
                root->dad->isBlack = true;
                granddad->right->isBlack = true;
                granddad->isBlack = false;
                root = granddad;
            }
            else {
                if (root == root->dad->right) {
                    root = root->dad;
                    leftRotate(root);
                }
                root->dad->isBlack = true;
                granddad->isBlack = false;
                rightRotate(granddad);
            }
        }
        else {
            if (granddad->left->isBlack == false) {
                root->dad->isBlack = true;
                granddad->left->isBlack = true;
                granddad->isBlack = false;
                root = granddad;
            }
            else {
                if (root == root->dad->left) {
                    root = root->dad;
                    rightRotate(root);
                }
                root->dad->isBlack = true;
                granddad->isBlack = false;
                leftRotate(granddad);
            }
        }
    }
    redoRoot();
}
void RBT::transplant(node* root, node* replace) {
    if (root->dad == NIL) {
        treeRoot = replace;
    }
    else if (root == root->dad->left) {
        root->dad->left = replace;
    }
    else root->dad->right = replace;
    replace->dad = root->dad;
}
void RBT::remove(int val) {
    node* child = NIL;
    node* z = search(val);
    if (z == NIL){
        cout << "-1\n";
        return;
    }
    node* y = z;
    bool origColor = y->isBlack;
    if (z->left == NIL) {
        child = z->right;
        transplant(z, z->right);
    }
    else if (z->right == NIL) {
        child = z->left;
        transplant(z, z->left);
    }
    else {
        node* aux = z->right;
        while (aux->left != NIL) aux = aux->left;
        y = aux;
        origColor = y->isBlack;
        child = y->right;
        if (y->dad == z) child->dad = y;
        // otherwise 
        else {
            transplant(y, y->right);
            y->right = z->right;
            y->right->dad = y;
        }
        transplant(z, y);
        y->left = z->left;
        y->left->dad = y;
        y->isBlack = z->isBlack;
    }
    if (origColor == true) remove_fix_up(child);
}
void RBT::remove_fix_up(node* root) {
    while (root != treeRoot && root->isBlack == true) {
        if (root == root->dad->left) {
            node* brother = root->dad->right;
            if (brother->isBlack == false) {
                brother->isBlack = true;
                root->dad->isBlack = false;
                leftRotate(root->dad);
                brother = root->dad->right;
            }
            if (brother->left->isBlack == true && brother->right->isBlack == true) {
                brother->isBlack = false;
                root = root->dad;
            }
            else {
                if (brother->right->isBlack == true) {
                    brother->left->isBlack = true;
                    brother->isBlack = false;
                    rightRotate(brother);
                    brother = root->dad->right;
                }
                brother->isBlack = root->dad->isBlack;
                root->dad->isBlack = true;
                brother->right->isBlack = true;
                leftRotate(root->dad);
                root = treeRoot;
            }
        }
        else if (root == root->dad->right) {
            node* brother = root->dad->left;
            if (brother->isBlack == false) {
                brother->isBlack = true;
                root->dad->isBlack = false;
                rightRotate(root->dad);
                brother = root->dad->left;
            }
            if (brother->left->isBlack == true && brother->right->isBlack == true) {
                brother->isBlack = false;
                root = root->dad;
            }
            else {
                if (brother->left->isBlack == true) {
                    brother->right->isBlack = true;
                    brother->isBlack = false;
                    leftRotate(brother);
                    brother = root->dad->left;
                }
                brother->isBlack = root->dad->isBlack;
                root->dad->isBlack = true;
                brother->left->isBlack = true;
                rightRotate(root->dad);
                root = treeRoot;
            }
        }
    }
    root->isBlack = true;
    redoRoot();
}

//MAIN
int main() {

#ifdef INFOARENA
    ifstream fin("zeap.in"); ofstream fout("zeap.out");
    cin.rdbuf(fin.rdbuf()); cout.rdbuf(fout.rdbuf());
#endif

    RBT arbore;
    string cerinta;

    while (cin >> cerinta) {
        ll val = 0; 
        if (cerinta == "I" || cerinta == "C" || cerinta == "S") cin >> val;
        if (cerinta[0] == 'I') {
            arbore.insert(val);
        }
        else if (cerinta[0] == 'C') {
            cout << arbore.inTree(val) << '\n';
        }
        else if (cerinta[0] == 'S') {
            arbore.remove(val);
        }
        else if (cerinta.length() > 1 && cerinta[2] == 'X') {
            // diferenta intre maxim si minim (succesorul lui 0, predecesorul lui INF) 
            ll minn = arbore.successor(0);
            ll maxx = arbore.predecessor(INF + 5);
            if (minn == -maxx) cout << "-1\n";
            else if (minn == maxx) cout << "-1\n";
            else cout << maxx - minn << '\n';
        }
        else if (cerinta.length() > 1 && cerinta[2] == 'N') {
            // minim de diferenta intre x si succesorul lui
            ll v1 = arbore.successor(0);
            ll v2 = arbore.successor(v1 + 1);
            //cout << v1 << ' ' << v2 << '\n';
            if (v1 == v2) cout << "-1\n";
            else if (v2 == INF) cout << "-1\n";
            else cout << arbore.sorted(v1, INF - 1) << '\n';
        }  
    }
    return 0;
}