Cod sursa(job #2924372)

Utilizator TheLostRevolverCalin Andrei TheLostRevolver Data 30 septembrie 2022 19:22:46
Problema Heapuri Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.6 kb
#include <fstream>
#include <cassert>

const int nMax = 200001;

struct nod {
    int val;
    int idx;

    bool operator<(const nod &nodNou) const {
        return val < nodNou.val;
    }

    bool operator>(const nod &nodNou) const {
        return val > nodNou.val;
    }
} heap[nMax];

int lastPozHeap = 0;

int idx[nMax];
int coIdx;

using namespace std;

void urcare(int pozi) {
    while (pozi > 1) { ///cat timp nu am ajuns in radacina heapului
        if (heap[pozi / 2] > heap[pozi]) { ///daca inca nu e respectata proprietatea de heap
            idx[heap[pozi].idx] = pozi / 2;  ///refacem pozitia elementelor in vectorul idx
            idx[heap[pozi / 2].idx] = pozi;

            ///interschimbam fiul cu tatal
            swap(heap[pozi], heap[pozi / 2]);
            pozi /= 2;
        } else {
            break; ///altfel, am terminat
        }
    }
}

void coborare(int pozi) {
    while (pozi * 2 <= lastPozHeap) { ///cat timp mai avem cel putin un fiu
        int pozCopilMin;
        if (pozi * 2 + 1 > lastPozHeap) { ///daca avem doar un fiu stang, acela este candidatul
            pozCopilMin = pozi * 2;
        } else {  ///altfel, luam ca candidat fiul cu valoare minima
            if (heap[pozi * 2] < heap[pozi * 2 + 1]) { ///op de comparare supraincarcat pt valuare
                pozCopilMin = pozi * 2;
            } else {
                pozCopilMin = pozi * 2 + 1;
            }
        }

        ///daca fiul cu valoare minima e mai mic decat tatal, ii interschimbam
        if (heap[pozi] > heap[pozCopilMin]) {
            ///refacem pozitile noi in vectorul idx
            idx[heap[pozi].idx] = pozCopilMin;
            idx[heap[pozCopilMin].idx] = pozi;

            ///interschimbam
            swap(heap[pozi], heap[pozCopilMin]);
            pozi = pozCopilMin;
        } else {
            break;///altfel, am terminat
        }
    }
}

void inserare(int nr) {

    lastPozHeap += 1;///adaugam in heap pe ultima pozitie (heapul este mereu continuu)
    coIdx += 1;  ///vectorul idx va avea in total cate elem unice s-au adaugat si pt elem nesterse va stii pe ce pozitie se gasesc in heapul heap


    heap[lastPozHeap].val = nr; ///nr adaugat
    heap[lastPozHeap].idx = coIdx;  ///aceasta valoare ramane constanta mereu

    idx[coIdx] = lastPozHeap; ///noul elem se afla acum pe ultima pozitie in heap

    urcare(lastPozHeap); ///refacem structura de min-Heap
}

void stergere(int idxi) {
    int pozi = idx[idxi];  /// pozitia in heap la care se afla elem intrat al idxi in multime

    heap[pozi] = heap[lastPozHeap]; ///il suprascriem cu elem aflat pe ultima pozitie in vectorul heap
    lastPozHeap--;///(pt ca nu are voie sa aiba goluri) si il stergem apoi scazand nr de elemente in heap


    ///elem poate doar sa urce sau doar sa coboare pt a reface structura de heap
    if (heap[pozi].val < heap[pozi / 2].val && pozi > 1)
        urcare(pozi);
    else
        coborare(pozi);
}

int main() {
    int n, op;
    ifstream fin("heapuri.in");
    ofstream fout("heapuri.out");
    fin >> n;
    for (int i = 0; i < n; i++) {
        fin >> op;

        switch (op) {
            case 1: {
                int nr;
                fin >> nr;
                inserare(nr);
                break;
            }
            case 2: {
                int idxi;
                fin >> idxi;
                stergere(idxi);
                break;
            }
            case 3: {
                fout << heap[1].val << '\n'; ///elem minim se afla in min-Heap in radacina
                break;
            }
            default:
                assert(false);
        }
    }
    fin.close();
    fout.close();
    return 0;
}