Cod sursa(job #2891331)

Utilizator AndreiAncutaAndrei Ancuta AndreiAncuta Data 18 aprilie 2022 11:24:31
Problema Heapuri Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.79 kb
#include <fstream>
#include <unordered_map>
#include <vector>

template <class T> class IndexHeap {
protected:
    using ValIndex = unsigned;
    using HeapIndex = int;
    std::vector<ValIndex> heap;
    std::vector<T> values;
    std::unordered_map<ValIndex, HeapIndex> index_in_heap;

    void swap_nodes(HeapIndex node1, HeapIndex node2) {
        std::swap(index_in_heap[heap[node1]], index_in_heap[heap[node2]]);
        std::swap(heap[node1], heap[node2]);
    }

    void sift_up(HeapIndex node) {
        HeapIndex parent = (node - 1) / 2;

        while (parent >= 0 && values[heap[parent]] > values[heap[node]]) {
            // Swap parent and node
            swap_nodes(parent, node);

            node = parent;
            parent = (node - 1) / 2;
        }
    }

    void sift_down(HeapIndex node) {
        HeapIndex left_child = 2 * node + 1;
        HeapIndex right_child = left_child + 1;

        while ((left_child < heap.size() && heap[node] > heap[left_child]) ||
               (right_child < heap.size() && heap[node] > heap[right_child])) {
            if (right_child >= heap.size() ||
                heap[left_child] > heap[right_child]) {
                swap_nodes(node, left_child);
                node = left_child;
            } else {
                swap_nodes(node, right_child);
                node = right_child;
            }

            left_child = 2 * node + 1;
            right_child = left_child + 1;
        }
    }

public:
    void insert(T x) {
        values.push_back(x);
        auto val_index = values.size() - 1;
        heap.push_back(val_index);
        index_in_heap[val_index] = heap.size() - 1;

        sift_up(index_in_heap[val_index]);
    }

    T get_min() const { return values[heap[0]]; }

    void remove(ValIndex index) {
        HeapIndex heap_index = index_in_heap[index];
        index_in_heap.erase(index);

        // Swap with last node and reduce heap
        swap_nodes(heap_index, heap.size() - 1);
        heap.pop_back();

        // The swapped node is now at heap_index
        HeapIndex parent = (heap_index - 1) / 2;
        if (parent >= 0 && heap[parent] > heap[heap_index]) {
            sift_up(heap_index);
        } else {
            sift_down(heap_index);
        }
    }
};

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

    unsigned n;
    ifs >> n;

    IndexHeap<int> heap;

    for (unsigned i = 0; i < n; i++) {
        int op;
        int x;
        ifs >> op;

        switch (op) {
        case 1:
            ifs >> x;
            heap.insert(x);
            break;
        case 2:
            ifs >> x;
            heap.remove(x - 1);
            break;
        case 3:
            ofs << heap.get_min() << '\n';
            break;
        }
    }

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

    return 0;
}