Cod sursa(job #3165077)

Utilizator Razvan48Capatina Razvan Nicolae Razvan48 Data 5 noiembrie 2023 13:17:04
Problema Heapuri cu reuniune Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 7.93 kb
#include <fstream>
#include <vector>
#include <climits>

using namespace std;

/// Heap Binomial

const int NMAX = 1e2;
const int QMAX = 3e5;
const int LOGQMAX = 19;

struct ArboreBinomial
{
    int valoare;
    int dimensiune;

    vector<ArboreBinomial*> fii;

    ArboreBinomial(int valoare) :
        valoare(valoare), dimensiune(0) {}

    ~ArboreBinomial()
    {
        for (int i = 0; i < this->fii.size(); ++i)
        {
            delete this->fii[i];
        }
    }
};

ArboreBinomial* multimi[1 + NMAX][1 + LOGQMAX];

int maxim(int index) /// avem garantia din input ca apelam asta cand multimea are macar un element
{
    int maxim = INT_MIN;
    int indexMaxim = -1;

    for (int i = 0; i < LOGQMAX; ++i)
    {
        if (multimi[index][i] != nullptr)
        {
            if (maxim < multimi[index][i]->valoare)
            {
                maxim = multimi[index][i]->valoare;
                indexMaxim = i;
            }
        }
    }

    vector<ArboreBinomial*> fii = multimi[index][indexMaxim]->fii;
    ArboreBinomial* carry = nullptr;
    ArboreBinomial* newCarry = nullptr;
    multimi[index][indexMaxim]->fii.clear();
    delete multimi[index][indexMaxim];
    multimi[index][indexMaxim] = nullptr;

    int indexFii = 0;
    for (int i = 0; i < LOGQMAX; ++i)
    {
        newCarry = nullptr;

        if (indexFii < fii.size() && i == fii[indexFii]->dimensiune)
        {
            if (multimi[index][i] == nullptr)
            {
                if (carry == nullptr)
                {
                    multimi[index][i] = fii[indexFii];
                }
                else
                {
                    ArboreBinomial* arbore1 = carry;
                    ArboreBinomial* arbore2 = fii[indexFii];

                    if (arbore1->valoare < arbore2->valoare)
                        swap(arbore1, arbore2);

                    arbore1->fii.emplace_back(arbore2);
                    ++arbore1->dimensiune;

                    newCarry = arbore1;
                }
            }
            else
            {
                ArboreBinomial* arbore1 = multimi[index][i];
                ArboreBinomial* arbore2 = fii[indexFii];

                if (arbore1->valoare < arbore2->valoare)
                    swap(arbore1, arbore2);

                arbore1->fii.emplace_back(arbore2);
                ++arbore1->dimensiune;

                newCarry = arbore1;

                multimi[index][i] = nullptr;

                if (carry)
                {
                    multimi[index][i] = carry;
                }
            }

            ++indexFii;
        }
        else
        {
            if (carry != nullptr)
            {
                if (multimi[index][i] == nullptr)
                {
                    multimi[index][i] = carry;
                }
                else
                {
                    ArboreBinomial* arbore1 = multimi[index][i];
                    ArboreBinomial* arbore2 = carry;

                    if (arbore1->valoare < arbore2->valoare)
                        swap(arbore1, arbore2);

                    arbore1->fii.emplace_back(arbore2);
                    ++arbore1->dimensiune;

                    newCarry = arbore1;

                    multimi[index][i] = nullptr;
                }
            }
        }

        carry = newCarry;
    }

    return maxim;
}

void insereaza(int index, int x)
{
    ArboreBinomial* carry = new ArboreBinomial(x);
    ArboreBinomial* newCarry = nullptr;

    for (int i = 0; i < LOGQMAX; ++i)
    {
        newCarry = nullptr;

        if (multimi[index][i] == nullptr)
        {
            multimi[index][i] = carry;
        }
        else
        {
            if (carry != nullptr)
            {
                ArboreBinomial* arbore1 = multimi[index][i];
                ArboreBinomial* arbore2 = carry;

                if (arbore1->valoare < arbore2->valoare)
                    swap(arbore1, arbore2);

                arbore1->fii.emplace_back(arbore2);
                ++arbore1->dimensiune;

                newCarry = arbore1;

                multimi[index][i] = nullptr;
            }
        }

        carry = newCarry;
    }
}

void uneste(int index1, int index2)
{
    ArboreBinomial* carry = nullptr;
    ArboreBinomial* newCarry = nullptr;

    for (int i = 0; i < LOGQMAX; ++i)
    {
        newCarry = nullptr;

        if (multimi[index1][i] == nullptr && multimi[index2][i] == nullptr)
        {
            if (carry != nullptr)
            {
                multimi[index1][i] = carry;
            }
        }
        else if (multimi[index1][i] == nullptr && multimi[index2][i] != nullptr)
        {
            if (carry == nullptr)
            {
                multimi[index1][i] = multimi[index2][i];
            }
            else
            {
                ArboreBinomial* arbore1 = carry;
                ArboreBinomial* arbore2 = multimi[index2][i];

                if (arbore1->valoare < arbore2->valoare)
                    swap(arbore1, arbore2);

                arbore1->fii.emplace_back(arbore2);
                ++arbore1->dimensiune;

                newCarry = arbore1;
            }
        }
        else if (multimi[index1][i] != nullptr && multimi[index2][i] == nullptr)
        {
            if (carry != nullptr)
            {
                ArboreBinomial* arbore1 = carry;
                ArboreBinomial* arbore2 = multimi[index1][i];

                if (arbore1->valoare < arbore2->valoare)
                    swap(arbore1, arbore2);

                arbore1->fii.emplace_back(arbore2);
                ++arbore1->dimensiune;

                newCarry = arbore1;

                multimi[index1][i] = nullptr;
            }
        }
        else
        {
            if (carry == nullptr)
            {
                ArboreBinomial* arbore1 = multimi[index2][i];
                ArboreBinomial* arbore2 = multimi[index1][i];

                if (arbore1->valoare < arbore2->valoare)
                    swap(arbore1, arbore2);

                arbore1->fii.emplace_back(arbore2);
                ++arbore1->dimensiune;

                newCarry = arbore1;

                multimi[index1][i] = nullptr;
            }
            else
            {
                ArboreBinomial* arbore1 = multimi[index2][i];
                ArboreBinomial* arbore2 = multimi[index1][i];

                if (arbore1->valoare < arbore2->valoare)
                    swap(arbore1, arbore2);

                arbore1->fii.emplace_back(arbore2);
                ++arbore1->dimensiune;

                newCarry = arbore1;

                multimi[index1][i] = carry;
            }
        }

        carry = newCarry;
    }

    for (int i = 0; i < LOGQMAX; ++i)
    {
        multimi[index2][i] = nullptr;
    }
}

int main()
{
    ifstream in("mergeheap.in");
    ofstream out("mergeheap.out");

    ios_base::sync_with_stdio(false);
    in.tie(nullptr);

    int n, q;
    in >> n >> q;

    for (int i = 1; i <= NMAX; ++i)
        for (int j = 0; j < LOGQMAX; ++j)
            multimi[i][j] = nullptr;

    while (q--)
    {
        int tip;
        in >> tip;

        if (tip == 1)
        {
            int m, x;
            in >> m >> x;

            insereaza(m, x);
        }
        else if (tip == 2)
        {
            int m;
            in >> m;

            out << maxim(m) << '\n';
        }
        else
        {
            int a, b;
            in >> a >> b;

            uneste(a, b);
        }
    }

    for (int i = 1; i <= NMAX; ++i)
    {
        for (int j = 0; j < LOGQMAX; ++j)
        {
            if (multimi[i][j] != nullptr)
            {
                delete multimi[i][j];
            }
        }
    }

    in.close();
    out.close();

    return 0;
}