Cod sursa(job #2907195)

Utilizator toma_ariciuAriciu Toma toma_ariciu Data 29 mai 2022 11:51:19
Problema Zeap Scor 90
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.15 kb
#include <iostream>
#include <fstream>
#include <random>
#include <set>

using namespace std;

ifstream fin("zeap.in");
ofstream fout("zeap.out");

mt19937 gen(151121);

const int inf = 0x3f3f3f3f;
struct treap {
    int val, prio, sz, maxi, mini, mindiff;
    treap *left, *right;
};
treap *root;

set <int> prio_list;

int get_rand()
{
    int x = gen();
    while(prio_list.find(x) != prio_list.end())
        x = gen();
    prio_list.insert(x);
    return x;
}

void init(treap *root, int val)
{
    root->val = val;
    root->prio = get_rand();
    // cout << root->val << ' ' << root->prio << '\n';
    root->sz = 1, root->maxi = val, root->mini = val, root->mindiff = inf;
}

int get_size(treap *root)
{
    if(root == NULL)
        return 0;
    return root->sz;
}

int get_max(treap *root)
{
    if(root == NULL)
        return 0;
    return root->maxi;
}

int get_min(treap *root)
{
    if(root == NULL)
        return inf;
    return root->mini;
}

int get_diff(treap *root)
{
    if(root == NULL)
        return inf;
    return root->mindiff;
}

void update_treap(treap *root)
{
    root->sz = get_size(root->left) + get_size(root->right) + 1;
    root->maxi = max(root->val, get_max(root->right));
    root->mini = min(root->val, get_min(root->left));
    root->mindiff = min(get_diff(root->left), get_diff(root->right));
    if(root->left != NULL)
        root->mindiff = min(root->mindiff, root->val - get_max(root->left));
    if(root->right != NULL)
        root->mindiff = min(root->mindiff, get_min(root->right) - root->val);
}

void split_treap(treap *root, treap *&left, treap *&right, int val)
{
    if(root == NULL)
    {
        left = NULL;
        right = NULL;
        return;
    }
    if(root->val <= val)
    {
        split_treap(root->right, root->right, right, val);
        left = root;
    }
    else
    {
        split_treap(root->left, left, root->left, val);
        right = root;
    }
    update_treap(root);
}

void merge_treap(treap *&root, treap *left, treap *right)
{
    if(left == NULL)
    {
        root = right;
        update_treap(root);
        return;
    }
    if(right == NULL)
    {
        root = left;
        update_treap(root);
        return;
    }
    if(left->prio > right->prio)
    {
        merge_treap(left->right, left->right, right);
        root = left;
    }
    else
    {
        merge_treap(right->left, left, right->left);
        root = right;
    }
    update_treap(root);
}

bool cautbin_treap(treap *root, int val)
{
    if(root == NULL)
        return 0;
    if(root->val == val)
        return 1;
    if(root->val > val)
        return cautbin_treap(root->left, val);
    if(root->val < val)
        return cautbin_treap(root->right, val);
}

void insert_treap(int val)
{
    if(cautbin_treap(root, val))
        return;
    treap *left, *right;
    treap *curr = new treap;
    init(curr, val);
    split_treap(root, left, right, val);
    merge_treap(left, left, curr);
    merge_treap(root, left, right);
}

void erase_treap(int val)
{
    if(!cautbin_treap(root, val))
    {
        fout << "-1\n";
        return;
    }
    treap *left, *right, *aux;
    split_treap(root, left, right, val - 1);
    split_treap(right, aux, right, val);
    merge_treap(root, left, right);
}

int main()
{
    string op;
    int x;
    while(fin >> op)
    {
        //cout << op << '\n';
        if(op == "I")
        {
            fin >> x;
            insert_treap(x);
        }
        if(op == "S")
        {
            fin >> x;
            erase_treap(x);
        }
        if(op == "C")
        {
            fin >> x;
            fout << cautbin_treap(root, x) << '\n';
        }
        if(op == "MAX")
        {
            if(get_size(root) < 2)
                fout << "-1\n";
            else
                fout << get_max(root) - get_min(root) << '\n';
        }
        if(op == "MIN")
        {
            if(get_size(root) < 2)
                fout << "-1\n";
            else
                fout << get_diff(root) << '\n';
        }
    }
    return 0;
}