Cod sursa(job #2899093)

Utilizator AndreiAncutaAndrei Ancuta AndreiAncuta Data 7 mai 2022 19:33:07
Problema Zeap Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.72 kb
#include <fstream>
#include <queue>
#include <set>
#include <tuple>

class Zeap {
    std::set<int> set;
    using Diff = std::tuple<int, int, int>;
    std::priority_queue<Diff, std::vector<Diff>, std::greater<Diff>> diff_heap;

    std::pair<decltype(set)::iterator, decltype(set)::iterator>
    find_neighbors(decltype(set)::iterator x_iter) {
        return {std::prev(x_iter), std::next(x_iter)};
    }

public:
    void insert(int x) {
        set.insert(x);
        auto x_iter = set.find(x);
        auto neighbors = find_neighbors(x_iter);
        auto pred = neighbors.first;
        auto succ = neighbors.second;

        if (x_iter != set.begin()) {
            diff_heap.push({x - *pred, x, *pred});
        }
        if (succ != set.end()) {
            diff_heap.push({*succ - x, *succ, x});
        }
    }

    bool erase(int x) {
        auto x_iter = set.find(x);

        if (x_iter == set.end()) {
            return false;
        }

        auto neighbors = find_neighbors(x_iter);
        auto pred = neighbors.first;
        auto succ = neighbors.second;

        if (x_iter != set.begin() && succ != set.end()) {
            diff_heap.push({*succ - *pred, *succ, *pred});
        }

        set.erase(x_iter);
        return true;
    }

    bool contains(int x) { return set.find(x) != set.end(); }

    int max_diff() {
        if (set.size() < 2) {
            return -1;
        }

        return *set.rbegin() - *set.begin();
    }

    int min_diff() {
        auto invalidated_diff = [&](const std::tuple<int, int, int> &diff) {
            auto term1 = std::get<1>(diff);
            auto term2 = std::get<2>(diff);

            return set.find(term1) == set.end() || set.find(term2) == set.end();
        };

        // Ignore diffs whose terms are no longer in the set
        while (!diff_heap.empty() && invalidated_diff(diff_heap.top())) {
            diff_heap.pop();
        }

        if (diff_heap.empty()) {
            return -1;
        }

        return std::get<0>(diff_heap.top());
    }
};

int main() {
    std::ifstream ifs("zeap.in");
    std::ofstream ofs("zeap.out");

    Zeap zeap;

    std::string action;
    while (ifs >> action) {
        if (action == "MAX") {
            ofs << zeap.max_diff() << '\n';
        } else if (action == "MIN") {
            ofs << zeap.min_diff() << '\n';
        } else {
            int x;
            ifs >> x;

            if (action == "I") {
                zeap.insert(x);
            } else if (action == "S") {
                if (!zeap.erase(x)) {
                    ofs << "-1\n";
                }
            } else if (action == "C") {
                ofs << (zeap.contains(x) ? 1 : 0) << '\n';
            }
        }
    }

    ofs.close();
    ifs.close();

    return 0;
}