Cod sursa(job #3125221)

Utilizator CraniXortDumitrescul Eduard CraniXort Data 2 mai 2023 12:36:50
Problema Heapuri cu reuniune Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.88 kb
#include <iostream>
#include <list>
#include <algorithm>
#include <fstream>

class BinomialHeap {
public:
    struct Node {
        long long value, degree;
        Node *child, *sibling, *parent;
    };

private:
    std::list <Node*> roots;


public:
    void print(std::ostream&) const;
    static void printTree(std::ostream&, Node*);
    static Node* newNode(long long value);
    static Node* mergeTrees(Node*, Node*);

    void insertTree(Node*);
    void unionHeap(std::list <Node*>);
    void unionHeap(const BinomialHeap& );

    void addValue(long long);

    long long getMin() const;
    void deleteMin();
    bool empty() const;

    ~BinomialHeap();
};



void BinomialHeap::print(std::ostream &out) const{
    for(auto& it: this->roots) {
        BinomialHeap::printTree(out, it);
    }

}

void BinomialHeap::printTree(std::ostream &out, Node *node) {
    out << node->value << " " << node->degree << '\n';
    Node *it = node->child;
    while(it != nullptr) {
        BinomialHeap::printTree(out, it);
        it = it->sibling;
    }
}

BinomialHeap::Node *BinomialHeap::newNode(long long value) {
    Node *temp = new Node;
    temp->value = value;
    temp->degree = 0;
    temp->child = nullptr;
    temp->sibling = nullptr;
    temp->parent = nullptr;
    return temp;
}

BinomialHeap::Node *BinomialHeap::mergeTrees(BinomialHeap::Node *a, BinomialHeap::Node *b) {
    if(a->value < b->value) {
        std::swap(a, b);
    }
    a->sibling = b->child;
    a->parent = b;
    b->child = a;
    b->degree ++;

    return b;
}

void BinomialHeap::unionHeap(std::list<Node *> heap) {
    std::list <Node*> temp;
    std::list<Node*>::iterator i;
    std::list<Node*>::iterator j;
    i = this->roots.begin();
    j = heap.begin();

    Node* carry = nullptr;

    while(i != this->roots.end() and j != heap.end()){
        if(carry != nullptr) {
            if((*i)->degree == (*j)->degree and carry->degree) {
                temp.push_back(carry);
                carry = nullptr;
            }
            else if((*i)->degree == carry->degree) {
                carry = BinomialHeap::mergeTrees(*i, carry);
                i ++;
            }
            else if((*j)->degree == carry->degree) {
                carry = BinomialHeap::mergeTrees(*j, carry);
                j ++;
            }
            else {
                temp.push_back(carry);
                carry = nullptr;
            }
            continue;
        }

        if((*i)->degree == (*j)->degree) {
            carry = BinomialHeap::mergeTrees(*i, *j);
            i ++;
            j ++;
        }
        else if((*i)->degree < (*j)->degree) {
            temp.push_back(*i);
            i ++;
        }
        else {
            temp.push_back(*j);
            j ++;
        }
    }


    while(i != this->roots.end()) {
        if(carry != nullptr and (*i)->degree == carry->degree) {
            carry = BinomialHeap::mergeTrees(*i, carry);
            i ++;
        }
        else if(carry != nullptr) {
            temp.push_back(carry);
            carry = nullptr;
        }
        else {
            temp.push_back(*i);
            i ++;
        }
    }

    while(j != heap.end()) {
        if(carry != nullptr and (*j)->degree == carry->degree) {
            carry = BinomialHeap::mergeTrees(*j, carry);
            j ++;
        }
        else if(carry != nullptr) {
            temp.push_back(carry);
            carry = nullptr;
        }
        else {
            temp.push_back(*j);
            j ++;
        }
    }
    if(carry != nullptr) {
        temp.push_back(carry);
        carry = nullptr;
    }
    this->roots = temp;
//    for(auto it: this->roots) {
//        std::cout << it->degree << ' ';
//    }
//    std::cout << '\n';
}

void BinomialHeap::insertTree(BinomialHeap::Node *node) {
    std::list <Node*> temp;
    temp.push_back(node);
    this->unionHeap(temp);

}

void BinomialHeap::addValue(long long value) {
//    std::cout << "add\n";
    this->insertTree(BinomialHeap::newNode(value));
}

long long BinomialHeap::getMin() const {
    long long temp = INT64_MAX;
    for(auto& it: this->roots) {
        temp = std::min(temp, it->value);
    }
    return temp;
}



void BinomialHeap::deleteMin() {
//    std::cout << "delete\n";
    std::list <Node*> temp;
    long long min = this->getMin();
    Node* node = nullptr;
    for(auto& it: this->roots) {
        if(it->value == min) {
            node = it;
            this->roots.remove(it);
            break;
        }
    }

    if(node == nullptr) {
        return;
    }
//    int prevSize = 101;
//    int currentSize = 100;
    Node *it = node->child;
    while(it != nullptr) {
        temp.push_back(it);
//        prevSize = currentSize;
//        currentSize = it->degree;
//        if(prevSize <= currentSize) {
//            std::cout << "not ok\n";
//        }
        it = it->sibling;
    }
    std::reverse(temp.begin(), temp.end());
//    for(auto it: temp) {
//        std::cout << it->degree << ' ';
//    }
//    std::cout << '\n';

    this->unionHeap(temp);
}

bool BinomialHeap::empty() const {
    return this->roots.empty();
}

void BinomialHeap::unionHeap(const BinomialHeap& heap) {
    this->unionHeap(heap.roots);
}

BinomialHeap::~BinomialHeap() {
    for(auto &it: this->roots) {
        if(it != nullptr) {
            delete it;
            it = nullptr;
        }
    }
}


int main() {
    std::ifstream fin("mergeheap.in");
    std::ofstream fout("mergeheap.out");
    int n, q;
    fin >> n >> q;

    BinomialHeap heap[n];

    while(q--) {
        int type, a, b;
        fin >> type;
        if(type == 1) {
            fin >> a >> b;
            heap[a-1].addValue(-b);
        }
        else if(type == 2) {
            fin >> a;
            fout << -heap[a-1].getMin() << '\n';
            heap[a-1].deleteMin();
        }
        else {
            fin >> a >> b;
            heap[a-1].unionHeap(heap[b-1]);
            heap[b-1] = BinomialHeap();
        }


    }

    return 0;
}