Cod sursa(job #2895746)

Utilizator 4N70N1U5Antonio Nitoi 4N70N1U5 Data 29 aprilie 2022 14:02:40
Problema Heapuri Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.25 kb
#include <fstream>
#include <utility>
#include <vector>

std::ifstream fin("heapuri.in");
std::ofstream fout("heapuri.out");

int N, Op, Val, Dim, Ord, Poz;
std::vector<int> Pozitii(200001);
std::vector< std::pair<int, int> > Heap(200001);

void percolate()
{
    while (Poz > 1 && Heap[Poz].first < Heap[Poz / 2].first)
    {
        std::swap(Heap[Poz], Heap[Poz / 2]);
        std::swap(Pozitii[Heap[Poz].second], Pozitii[Heap[Poz / 2].second]);
        Poz /= 2;
    }
    // Cat timp nu ma aflu in varful heap-ului si fiul este mai mic decat
    // tatal, urc fiul in locul tatalui.
}

void sift()
{
    int Fiu;

    do
    {
        Fiu = 0;
        // Plec de la presupunerea ca nodul nu mai are niciun fiu si
        // coborarea se opreste.

        if (Poz * 2 <= Dim)
        {
            Fiu = Poz * 2;
            // Daca nodul are fiu stang, atunci acesta este selectat.
            if (Poz * 2 + 1 <= Dim && Heap[Poz * 2 + 1].first < Heap[Poz * 2].first)
            {
                Fiu = Poz * 2 + 1;
                // Daca nodul are si fiu drept si fiul drept este mai mic decat
                // fiul stang, atunci fiul drept este preferat si este selectat
                // in locul fiului stang.
            }
            if (Heap[Fiu].first >= Heap[Poz].first)
            {
                Fiu = 0;
                // Daca cel mai mic dintre fii este mai mare sau egal cu tatal,
                // atunci niciun fiu nu mai este selectat si coborarea se opreste.
            }
        }

        if (Fiu)
        {
            std::swap(Heap[Poz], Heap[Fiu]);
            std::swap(Pozitii[Heap[Poz].second], Pozitii[Heap[Fiu].second]);
            Poz = Fiu;
            // Daca unul din fii a fost selectat, atunci cobor tatal
            // in locul fiului si continui.
        }
    } while (Fiu);
}

void inserare()
{
    Dim++; // Incrementez dimensiunea heap-ului.
    Ord++; // Incrementez numarul de elemente inserate.

    // Inserez elementul in heap pe ultima pozitie.
    
    Heap[Dim].first = Val; // Valoarea elementului.
    Heap[Dim].second = Ord; // Al catelea a fost inserat in heap.
    Pozitii[Ord] = Dim; // Pozitia pe care a fost inserat elementul in heap.

    Poz = Dim;

    percolate();
    // Urc elementul pana la locul lui, daca este cazul.
}

void stergere()
{
    Poz = Pozitii[Val];
    // Determin pe ce pozitie se afla elementul care trebuie sters.

    std::swap(Heap[Poz], Heap[Dim]);
    std::swap(Pozitii[Heap[Poz].second], Pozitii[Heap[Dim].second]);
    // Sterg elementul punand in locul lui ultimul element din heap
    // si pe el pe ultima pozitie.

    Dim--; // Decrementez dimensiunea heap-ului.

    if (Heap[Poz].first < Heap[Poz / 2].first)
        percolate();
        // Daca elementul pus in locul celui sters este mai mic
        // decat tatal, atunci il urc.
    else
        sift();
        // Altfel, il cobor.
}

int main()
{
    fin >> N;

    for (int i = 0; i < N; i++)
    {
        fin >> Op;

        switch (Op)
        {
        case 1:
            fin >> Val;
            inserare();
            break;

        case 2:
            fin >> Val;
            stergere();
            break;

        case 3:
            fout << Heap[1].first << '\n';
            break;
        
        default:
            break;
        }
    }
}