Cod sursa(job #2331771)

Utilizator puzzleFlutur Vasile puzzle Data 29 ianuarie 2019 21:54:22
Problema Heapuri Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.52 kb
#include <fstream>

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

#define Nmax 200003

int Heap[Nmax],Poz[Nmax],Valori[Nmax];
int Locatie, Nr_Nod;

/*
	Vectorul Valori[] retine valorile primite in urma efectuarii comenzii "1" in ordine cronologica
	Vectorul Heap[] spune unde in vectorul Valori[] se gaseste elementul cu numarul "i" in heap.
	Vectorul Poz[] are in Poz[i] pozitia (in heap) in care se afla A[i];
	Ultimele doua lucreaza foarte bine impreuna: Poz[Heap[i]] va fi intotdeauna egal cu "i";

*/

inline void Swap (int x, int y)
{
	int aux = Heap[x];
	Heap[x] = Heap[y];
	Heap[y] = aux;
}

/*
	Heap-ul are proprietatea ca tatal unui fiu "x" este intotdeauna egal cu "x/2".
	Cand introducem un element in heap, il introducem in ultima pozitie (care devine parametrul x al functiei).
	Urmeaza apoi un proces de filtrare in caz ca locul acestuia nu este acolo.
	Se verifica daca acesta este mai mic decat tatal acestui, in acest caz, locul lor in Heap[]
	(care tine minte pozitia in heap a fiecarui element) se interschimba (functia Swap de mai sus).
	Note: Nu se schimba pozitia lor in vectorul Valori[] deoarece avem nevoie pentru a extrage elementele in ordine cronologica.
	Dupa ce au fost schimbate aceste valori, se updateaza vectorul Poz[] (proprietatea ca Poz[Heap[x]] = x, oricare ar fi x)
	Se continua recursiv pana cand valoarea introdusa ajunge in pozitia potrivita.

*/
void push(int Son)
{
	int Father = Son/2;

	if(Father && Valori[Heap[Father]] > Valori[Heap[Son]])
	{
		Swap(Son,Father);

		Poz[Heap[Son]] = Son;
		Poz[Heap[Father]] = Father;

		push(Father);
	}
}

/*
	Functia pop() primeste ca parametru o pozitie x care devine tatal si verifica daca fii acestuia sunt mai mici decat el.
	Daca se ajunge la concluzia ca sunt mai mici, se interschimba pentru a pastra proprietatile heap-ului.
	De asemenea, nu se uita si schimbarea pozitiilor in vectorul Poz[]
*/

void pop(int x)
{
    int y = 0;

    while(x!=y)
    {
        y = x;

        if(y*2 <= Locatie && Valori[Heap[x]] > Valori[Heap[y*2]]) x = y*2;
        if(y*2+1 <= Locatie && Valori[Heap[x]] > Valori[Heap[y*2+1]]) x = y*2+1;

        Swap(x,y);

        Poz[Heap[x]] = x;
        Poz[Heap[y]] = y;
    }
}
/*
void Log()
{
	for (int i =1; i<=Nr_Nod; i++)
		out<<Heap[i]<<" ";
}
*/
int main()
{
	int numberOfCases;
	in >> numberOfCases;

	int Case,x;

	for(int i = 1; i <= numberOfCases; i++)
	{
		in >>Case;
		if(Case == 1)
		{
			in >> x;
			//Pregatire pentru rularea functiei push()
			Nr_Nod++;
			Locatie++;

			Valori[Nr_Nod] = x;
			Heap[Locatie] = Nr_Nod;
			Poz[Nr_Nod] = Locatie;

			push(Locatie);

		}
		if(Case == 2)
		{
			in >> x;
			//Valoare care trebuie extrasa este inlocuita cu -1 in vectorul cu Valori
			//Apoi, profitand de acest lucru, este adusa in prima pozitie din heap cu functia push()

			Valori[x] = -1;
			push(Poz[x]);

			//Odata adus pe prima pozitie, acesta este inlocuit in vectorul Heap[] cu ultimul element din heap si apoi i se noteaza noua pozitie in Poz[]
			Poz[Heap[x]] = 0;
			Heap[1] = Heap[Locatie];
			--Locatie;
			Poz[Heap[x]] = 1;

			//Odata adus ultimul element pe prima pozitie, acesta se filtreaza pana ajunge pe pozitia potrivita
			//Acest proces presupune verificarea daca fii sai sunt mai mici decat el si inlocuirea acestuia cu unul dintre ei
			//Fii unui tata au intotdeauna pozitia x*2 si x*2+1

			pop(1);
		}
		if(Case == 3)
		{
			out<<Valori[Heap[1]]<<'\n';
		}
	}
	//Log();
	return 0;
}