Cod sursa(job #3127835)

Utilizator darius1843Darius Suditu darius1843 Data 7 mai 2023 21:08:42
Problema Heapuri cu reuniune Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 7.39 kb
#include <fstream>
#include <list>
#include <queue>


using namespace std;
ifstream in("mergeheap.in");
ofstream out("mergeheap.out");

class BinomialHeap
{
private:
    struct Node {
        int value;
        int grad;
        Node* child;
        Node* sibling;
        Node* parent;

        Node() : value(0), grad(0), child(nullptr), sibling(nullptr), parent(nullptr) {}
        Node(int val) : value(val), grad(0), child(nullptr), sibling(nullptr), parent(nullptr) {}
    };

    list <Node*> heap;


    /*Node* get_max() {
        
        Node* vmax = new Node;
        vmax->value = -1;

        Node* root = nullptr;
        for (Node* n : heap) {
            if (n->value > vmax->value) {
                vmax = n;
                root = n;
            }
        }
        return root;
    }*/




    Node* mergetree(Node* t1, Node* t2)
    {
        /*if (t1 == nullptr || t2 == nullptr) {
            return;
        }*/

        if (t2->value > t1->value) {
            Node* aux = t1;
            t1 = t2;
            t2 = aux;
        }

        t2->sibling = t1->child;
        t1->grad++;
        t2->parent = t1;
        t1->child = t2;

        return t1;
    }


    /*void adjust() {

    if (heap.size() <= 1) {
        return;
    }

    Node* ant = heap.front();
    Node* curent = ant->sibling;
    Node* urm;

    if (curent == nullptr)
        urm = nullptr;
 
    else
        urm = curent->sibling;
 


    while (curent != nullptr)
    {
        while (ant->grad == curent->grad && (urm == nullptr || urm->grad > curent->grad))
        {
            mergeheap(curent, ant);
            if (ant == heap.front()) {
                heap.pop_front();
                heap.push_front(curent);
                ant = heap.front();
            }
            else 
                ant = ant->sibling;

            curent = curent->sibling;

            if (curent == nullptr)
                urm = nullptr;

            else 
                urm = curent->sibling;
        }
        ant = curent;
        curent = urm;

        if (curent == nullptr) 
            urm = nullptr;

        else
            urm = curent->sibling;

    }
}*/

    void adjust() {
        heap.sort([](Node* a, Node* b) { return a->grad < b->grad; });
        if (heap.size() <= 1) {
            return;
        }
        else {
            auto previous = heap.begin();
            auto current = previous;
            current++;
            auto next = current;
            next++;

            while (current != heap.end()) {
                if (next != heap.end()) {
                    if ((*previous)->grad == (*current)->grad && (*current)->grad != (*next)->grad) {
                        *previous = mergetree(*previous, *current);
                        current = heap.erase(current);
                        next++;
                    }
                    else {
                        previous++;
                        current++;
                        next++;
                    }
                }
                else {
                    if ((*previous)->grad == (*current)->grad) {
                        *previous = mergetree(*previous, *current);
                        heap.pop_back();
                    }

                    current = heap.end();
                }
            }
        }
    }







public:
    void insert(int val) {

        Node* tree = new Node;
        tree->value = val;
        heap.push_back(tree);
        adjust();
    }


    /*int top() {
        return (*get_max()).value;
    }*/

    


    void MergeHeap(BinomialHeap& heap2) {
        list<Node*> heapFinal;

        Node* h1_node;
        if (heap.empty())
            h1_node = nullptr;
       
        else
            h1_node = heap.front();
       

        Node* h2_node;
        if (heap2.heap.empty())
            h2_node = nullptr;
        
        else
            h2_node = heap2.heap.front();
        

        while (h1_node != nullptr && h2_node != nullptr)
            if (h1_node->grad <= h2_node->grad)
            {
                heapFinal.push_back(h1_node);
                heap.pop_front();
                if (heap.empty())
                    h1_node = nullptr;
               
                else
                    h1_node = heap.front();
                
            }
            else
            {
                heapFinal.push_back(h2_node);
                heap2.heap.pop_front();
                if (heap2.heap.empty())
                    h2_node = nullptr;
                
                else
                    h2_node = heap2.heap.front();
                
            }
    

        while (h1_node != nullptr) {
            heapFinal.push_back(h1_node);
            heap.pop_front();

            if (heap.empty())
                h1_node = nullptr;
            
            else
                h1_node = heap.front();
            

        }

        while (h2_node != nullptr) {
            heapFinal.push_back(h2_node);
            heap2.heap.pop_front();

            if (heap2.heap.empty())
                h2_node = nullptr;
            
            else
                h2_node = heap2.heap.front();
           
        }

        heap = heapFinal;
        adjust();
    }


    int extract_max() {
        if (heap.empty()) {
            throw runtime_error("Heap is empty");
        }

        Node* vmax = new Node;
        vmax->value = -1;

        Node* max_node = nullptr;
        Node* root = nullptr;
        for (Node* n : heap) {
            if (n->value > vmax->value) {
                vmax = n;
                max_node = n;
                root = n;
            }
        }

        int max_value = max_node->value;

        heap.remove(max_node);

        Node* child = max_node->child;
        while (child != nullptr) {
            Node* sibling = child->sibling;
            child->sibling = nullptr;
            heap.push_front(child);
            child = sibling;
        }

        adjust();
        return max_value;
    }



    
    /*void print_heap() {
        for (Node* n : heap) {
            queue<Node*> q;
            q.push(n);
            while (!q.empty()) {
                Node* curent = q.front();
                q.pop();
                out << curent->value << " ";
                if (curent->child != nullptr) {
                    q.push(curent->child);
                    Node* sibling = curent->child->sibling;
                    while (sibling != nullptr) {
                        q.push(sibling);
                        sibling = sibling->sibling;
                    }
                }
            }
            out << endl;
        }
    }*/


};

int N, Q, nop, poz1, poz2;
BinomialHeap heap[105];

int main()
{
    

    in >> N >> Q;
    for (int i = 1; i <= Q; i++)
    {
        in >> nop;
        if (nop == 1)
        {
            in >> poz1 >> poz2;
            heap[poz1].insert(poz2);
        }
        if (nop == 2)
        {
            in >> poz1;
            out<<heap[poz1].extract_max();
            out << endl;
        }
        if (nop == 3)
        {
            in >> poz1 >> poz2;
            heap[poz1].MergeHeap(heap[poz2]);
        }
    }


    return 0;
}