Cod sursa(job #322504)

Utilizator tomescu_alinTomescu Alin tomescu_alin Data 8 iunie 2009 22:58:32
Problema Heapuri Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 5.19 kb
/* 
	Author's name: Alin Tomescu 
	Website: http://alinush.isgreat.org 
	Date: 10:57 PM Monday, June 08, 2009
*/

#include <iostream>
#include <fstream>
using namespace std;

typedef unsigned long ulong;

const ulong MAX_OPERATIONS = 200000+1;

class SpecialHeap 
{
	public:
		SpecialHeap()
			:	heapSize(0), indexCounter(0)
		{}
	
	public:
		//	Pushes a new number on the heap
		void push(ulong number);
		//	Pops the number with that index off the heap
		void pop(ulong id);
		//	Returns the min. number in the heap
		ulong peek() const;
	
	private:
		//	Internal heap array related operations
		ulong getParent 	(ulong index) const { return (index-1)/2; }
		ulong getLeftChild 	(ulong index) const { return 2*index+1; }
		ulong getRightChild	(ulong index) const { return 2*index+2; }
		
		bool hasLeftChild 	(ulong index) const { return 2*index+1 < heapSize; }	
		bool hasRightChild 	(ulong index) const { return 2*index+2 < heapSize; }
		bool hasChildren	(ulong index) const { return hasLeftChild(index); }
		
		bool isRoot		(ulong index) const { return index == 0; }
		bool hasParent	(ulong index) const { return !isRoot(index); }
	
	private:
		ulong value(ulong id) const { return idToNumber[id]; }
		bool areMappingsValid() const;
	
	private:
		//	Each number is going to have an index or key or whatever you want to call it.
		//	The value of a number's index is the time (expressed as a number) when that
		//	number was inserted into the heap.
		//	Example:
		//		The index for the firstly inserted item is 0
		//		The index for the secondly inserted item is 1
		//		And so on, the index for the n'th inserted item is n-1		
		
		//	Maps an index to a number. This is where the actual numbers are stored.
		ulong idToNumber[MAX_OPERATIONS];
		
		//	Maps an index to its position in the internal heap array.
		//	(We need this for fast lookup when removing from the heap)
		ulong idToHeapPos[MAX_OPERATIONS];
		
		//	Keeps a min-heap of the numbers but instead of storing the values it stores their indices
		ulong heapOfIds[MAX_OPERATIONS];
	
		ulong heapSize;		//	The current number of elements in the heap
		ulong indexCounter;	//	The current index counter (this goes from 0 to inf)	
};

ulong SpecialHeap::peek() const 
{
	return idToNumber[heapOfIds[0]];
}

void SpecialHeap::push(ulong number)
{
	//	Store the number in the id-to-number map
	ulong id = indexCounter++;
	idToNumber[id] = number;
	
	//	Now we need to actually put that number's id in the heap
	
	//	So we start by putting it at the "end" of the heap-array
	ulong heapIndex = heapSize++;
	heapOfIds[heapIndex] = id;
	idToHeapPos[id] = heapIndex;
	
	//	And then we sift it up...
	//	But each time we swap an element while sifting we need to update
	//	our 'idToHeapPos' array with the new mapping
	while(hasParent(heapIndex))
	{
		ulong parentHeapIndex = getParent(heapIndex);
		ulong parentId = heapOfIds[parentHeapIndex];
		if(value(id) < value(parentId))
		{
			//	Swap the two...
			std::swap(heapOfIds[heapIndex], heapOfIds[parentHeapIndex]);
			std::swap(idToHeapPos[id], idToHeapPos[parentId]);
			
			heapIndex = parentHeapIndex;
		}
		else
		{
			break;
		}
	}
}

void SpecialHeap::pop(ulong deletedId)
{
	ulong lastId = heapOfIds[heapSize-1];
	ulong heapIndex = idToHeapPos[deletedId];
	
	//	Replace the deleted element with the last one in the heap
	heapOfIds[heapIndex] = lastId;
	heapSize--;
	
	//	Update the id-to-heap-pos mapping
	idToHeapPos[lastId] = heapIndex;
	
	
	while(hasChildren(heapIndex))
	{
		//	If one of the element's children is smaller 
		//	than the element, then we need to swap the two
		
		//	Get the minimum child.
		//	We know there's a left child 
		//	since that's the precondition for the loop.
		ulong childHeapIndex = getLeftChild(heapIndex);
		ulong childId = heapOfIds[childHeapIndex];
		
		if(hasRightChild(heapIndex))
		{
			//	Compare the two and store the minimum one...
			ulong rightChildHeapIndex = getRightChild(heapIndex);
			ulong rightChildId = heapOfIds[rightChildHeapIndex];
			
			if(value(rightChildId) < value(childId))
			{
				childHeapIndex = rightChildHeapIndex;
				childId = rightChildId;
			}
		}
		
		if(value(childId) < value(lastId))
		{
			//	Swap with the minimum
			std::swap(heapOfIds[heapIndex], heapOfIds[childHeapIndex]);
			std::swap(idToHeapPos[lastId], idToHeapPos[childId]);
			
			heapIndex = childHeapIndex;
		}
		else 
		{
			break;
		}
	}
}

int main()
{
	const char * inFile = "heapuri.in";
	const char * outFile = "heapuri.out";
	
	ulong nOperations;
	
	ifstream fin(inFile);
	ofstream fout(outFile);

	fin >> nOperations;
	
	// Our "special" heap suited for this task
	SpecialHeap * heap = new SpecialHeap;
	
	for(ulong i = 0; i < nOperations; i++)
	{
		ulong op;
		ulong number = -1;
		
		fin >> op;

		switch(op)
		{
			case 1:
			{
				fin >> number;
				heap->push(number);
				break;
			}
			case 2:
			{
				fin >> number;
				// Our id mapping is off by one for convenience...
				heap->pop(number-1);
				break;
			}
			case 3:
			{
				fout << heap->peek() << "\n";
				break;
			}
		}
	}
	
	fout.close();
	fin.close();
	
	return 0;
}