Cod sursa(job #1747332)

Utilizator rangerChihai Mihai ranger Data 24 august 2016 19:09:42
Problema Zeap Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.16 kb
#include <bits/stdc++.h>
using namespace std;

multiset < int > St;
#define INEXISTENT  0
struct item
{
    int key, prior;
    item * l, * r;
    item(){}
    item(int key) : key(key), prior((rand()<<16) ^ rand()), l(NULL), r(NULL) {}
};


using pitem = item *;


pitem root;


void split(pitem t, int x, pitem& l, pitem& r)
{
    if (!t)
        l = r = NULL;
    else if (x >= t->key)
        split(t->r, x, t->l, r), l = t;
    else split(t->l,x, l, t->r), r = t;
}

void merge(pitem& t, pitem l, pitem r)
{
    if (!l || !r)
        t = l ? l : r;
    else if (l->prior >= r->prior)
        merge(l->r, l->r, r), t = l;
    else merge(r->l, l, r->l), t = r;
}


int MAX(pitem t)
{
    while(t->r) t = t->r;
    return t->key;
}
int MIN(pitem t)
{
    while(t->l) t = t->l;
    return t->key;
}

vector<pitem> findPath(pitem t)
{
    int key = t->key;
    pitem tmp = root;
    vector<pitem> rt;
    while(tmp->key != key)
    {
        rt.push_back(tmp);
        if (key <= tmp->key)
            tmp = tmp->l;
        else
            tmp = tmp->r;
    }
    rt.push_back(t);
    reverse(rt.begin(),rt.end());
    return rt;
}

int inorder_next(pitem t)
{
    int mx = MAX(root);
    if (t->key == mx)
        return INEXISTENT;
    if (t->r)
        return MIN(t->r);
    else {
        vector<pitem> vt = findPath(t);
        for(int i=1;i<vt.size();i++){
            if (vt[i]->l->key == vt[i-1]->key)
                return vt[i]->key;
        }
    }
}
int inorder_prev(pitem t)
{
    int mn = MIN(root);
    if (t->key == mn)
        return INEXISTENT;
    if (t->l)
        return MAX(t->l);

    vector<pitem> vt = findPath(t);
    for(int i=1;i<vt.size();i++){
        if (vt[i]->r->key == vt[i-1]->key)
            return vt[i]->key;
    }
}

void calc(pitem t, int tip = 1)
{
    if (tip)
    {
        int next = inorder_next(t);
        if (next != INEXISTENT) St.insert(next - t->key);
        int prev = inorder_prev(t);
        if (prev != INEXISTENT) St.insert(t->key - prev);
        if (next != INEXISTENT && prev != INEXISTENT)
            St.erase(St.find(next - prev));
    } else {
        int next = inorder_next(t);
        if (next != INEXISTENT) St.erase(St.find(next - t->key));
        int prev = inorder_prev(t);
        if (prev != INEXISTENT) St.erase(St.find(t->key - prev));
        if (next != INEXISTENT && prev != INEXISTENT)
            St.insert(next - prev);
    }
}


void insert(pitem& t, pitem it)
{
    if (!t)
        t = it, calc(it);
    else if (it->prior > t->prior)
        split(t, it->key, it->l, it->r), t = it, calc(it);
    else
        insert(it->key < t->key ? t->l : t->r , it);
}

int erase(pitem& t, int key)
{
    if (!t)
        return -1;
    if (t->key == key) {
        calc(t, 0);
        return merge(t, t->l, t->r), 1;
    }

    else
       return erase(key <= t->key ? t->l : t->r, key);
}

int find(pitem t, int key)
{
    if (!t)
        return 0;
    if (t->key == key)
        return 1;
    return find(key <= t->key ? t->l : t->r, key);
}

int cnt = 0;


int main()
{
    srand(time(NULL));

    string c;
    ifstream fin("zeap.in");
    ofstream fout("zeap.out");
    while (fin >> c)
    {
       // fout << c << endl;
        if (c == "I") {
            int val;
            fin>>val;
            cnt += !find(root, val);
            insert(root, new item(val));
        }
        if (c == "S"){
            int val;
            fin>>val;
            if (erase(root, val)==-1)
                fout << "-1\n";
                else cnt -= 1;
        }
        if (c == "C"){
            int val;
            fin>>val;
            fout << find(root, val) << '\n';
        }
        if (c == "MAX"){
            if (cnt < 2) {
                cout << "-1\n";
                continue;
            }
            fout << MAX(root) - MIN(root) << "\n";
        }
        if (c == "MIN"){
            if (cnt < 2) {
                cout << "-1\n";
                continue;
            }
            if (St.size())
                fout << *St.begin() << '\n';
        }
    }

}