Cod sursa(job #2906117)

Utilizator AndreiAncutaAndrei Ancuta AndreiAncuta Data 24 mai 2022 23:00:51
Problema Heapuri cu reuniune Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.23 kb
#include <exception>
#include <fstream>
#include <memory>
#include <vector>

template <class T> class Node;

template <class T> using NodePtrT = std::shared_ptr<Node<T>>;

template <class T> class Node {
protected:
    using NodePtr = NodePtrT<T>;
    T value;
    NodePtr next;
    NodePtr left;

public:
    Node(T value) : value(value), next(nullptr), left(nullptr) {}

    T getValue() const { return value; }

    NodePtr getLeftChild() const { return left; }
    void setLeftChild(const NodePtr &node) { left = node; }

    NodePtr getNextSibling() const { return next; }
    void setNextSibling(const NodePtr &node) { next = node; }

    void addChild(const NodePtr &node) {
        if (left != nullptr) {
            node->next = left;
        }
        left = node;
    }
};

template <class T, class Compare = std::less<T>> class PairingHeap {
protected:
    using NodePtr = NodePtrT<T>;
    NodePtr root;

    static NodePtr merge(const NodePtr &node1, const NodePtr &node2) {
        if (node1 == nullptr) {
            return node2;
        }

        if (node2 == nullptr) {
            return node1;
        }

        if (Compare()(node1->getValue(), node2->getValue())) {
            node1->addChild(node2);
            return node1;
        } else {
            node2->addChild(node1);
            return node2;
        }

        return nullptr;
    }

    static NodePtr twoPassMerge(const NodePtr &node) {
        if (node == nullptr || node->getNextSibling() == nullptr) {
            return node;
        }

        auto first = node;
        auto second = node->getNextSibling();
        auto rest = node->getNextSibling()->getNextSibling();

        first->setNextSibling(nullptr);
        second->setNextSibling(nullptr);

        return merge(merge(first, second), twoPassMerge(rest));
    }

public:
    bool empty() const { return root == nullptr; }

    T min() const {
        if (empty()) {
            throw std::out_of_range("Heap is empty");
        }
        return root->getValue();
    }

    void popMin() { root = twoPassMerge(root->getLeftChild()); }

    void insert(T x) { root = merge(root, std::make_shared<Node<T>>(x)); }

    void clear() { root = nullptr; }

    void absorb(PairingHeap<T, Compare> &rhs) {
        root = merge(root, rhs.root);
        rhs.root = nullptr;
    }
};

int main() {
    std::ifstream ifs("mergeheap.in");

    int heapCount, opCount;
    ifs >> heapCount >> opCount;

    std::vector<PairingHeap<int, std::greater<int>>> heaps(heapCount);

    std::ofstream ofs("mergeheap.out");

    for (int i = 0; i < opCount; ++i) {
        int op;
        ifs >> op;

        if (op == 1) {
            int heapIndex, x;
            ifs >> heapIndex >> x;

            --heapIndex;
            heaps[heapIndex].insert(x);
        } else if (op == 2) {
            int heapIndex;
            ifs >> heapIndex;
            --heapIndex;

            ofs << heaps[heapIndex].min() << '\n';
            heaps[heapIndex].popMin();
        } else {
            int heapIndex1, heapIndex2;
            ifs >> heapIndex1 >> heapIndex2;
            --heapIndex1;
            --heapIndex2;

            heaps[heapIndex1].absorb(heaps[heapIndex2]);
            heaps[heapIndex2].clear();
        }
    }

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

    return 0;
}