Cod sursa(job #1070871)

Utilizator dm1sevenDan Marius dm1seven Data 2 ianuarie 2014 11:27:57
Problema Heapuri Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 3.77 kb
#include <fstream>
using namespace std;

namespace e_024_heapuri
{
	template <typename T, int MAX_N>
	class heap
	{
	private:
		T a[MAX_N];
		int indexes[MAX_N]; //retrieves the original index of the position in heap
		int positions[MAX_N]; //give the position in heap for each index
		int N;
		
		int parent(int i) { return (i - 1) / 2; }
		inline int left_child(int i) { return 2 * i + 1;  }
		inline int right_child(int i) { return 2 * i + 2; }

	public:
		heap(): N(0) {}
		~heap() {}

		T operator () (int i)
		{
			return a[i];
		}

		void insert(T x, int index)
		{
			a[N] = x;
			positions[index] = N;
			indexes[N] = index;
			N++;
			update_position(N - 1);
		}

		void remove(int index)
		{
			//exchange with the last element
			int pos = positions[index];
			exchange_positions(pos, N - 1);
			//remove one element
			N--;
			//update the heap
			update_position(pos);
		}

	private:

		/**
		* Update the heap if the element at the given position has changed its value. 
		* Only upward updates are performed in the heap.
		* The new value might not respect the heap structure. The other elements are in the heap format.
		* Usefull after one element was inserted/deleted at the end of the vector.
		*/
		void update_position(int position)
		{
			int current_pos = position;
			int parent_pos;
			//upward updating
			while (current_pos > 0 && a[current_pos] < a[parent_pos = parent(current_pos)]) {
				//exchange the places in heap
				exchange_positions(current_pos, parent_pos);

				current_pos = parent_pos;
			}

			//downward updating
			int next_pos;
			//update only if upward updating wasn't performed
			if (current_pos == position) {
				while (current_pos >= 0)
				{
					next_pos = -1;

					//check the children of the current node and their values
					int pos_left_child = left_child(current_pos);
					int pos_right_child = right_child(current_pos);

					bool left_available = false, right_available = false;

					if (pos_left_child < N && a[pos_left_child] < a[current_pos]) {
						next_pos = pos_left_child; left_available = true;
					}
					if (pos_right_child < N && a[pos_right_child] < a[current_pos]) {
						next_pos = pos_right_child;
						right_available = true;
					}

					//if the node has two children choose the minimum child
					if (left_available && right_available) {
						if (a[pos_left_child] < a[pos_right_child]) next_pos = pos_left_child;
						else next_pos = pos_right_child;
					}

					//if necessary, exchange the places in heap
					if (next_pos >= 0) exchange_positions(current_pos, next_pos);

					current_pos = next_pos;
				}
			}
		}

		void exchange_positions(int pos_i, int pos_j)
		{
			//exchange the values
			T aux = a[pos_i];
			a[pos_i] = a[pos_j];
			a[pos_j] = aux;

			//get the original indexes at the given positions
			int index_i = indexes[pos_i];
			int index_j = indexes[pos_j];

			//exchange the positions
			positions[index_i] = pos_j;
			positions[index_j] = pos_i;

			//exchange the indexes
			indexes[pos_i] = index_j;
			indexes[pos_j] = index_i;
		}
	};
}

//int e_024_heapuri()
int main()
{
	string in_file = "heapuri.in";
	string out_file = "heapuri.out";

	int N;
	const int MAX_N = 200000;

	e_024_heapuri::heap<int, MAX_N> heap_;

	ifstream ifs(in_file);
	ofstream ofs(out_file);
	ifs >> N;
	int index = -1;
	for (int i = 0; i < N; i++) {
		int op;
		ifs >> op;
		if (op == 1) {			
			index++;
			int x;
			ifs >> x;
			heap_.insert(x, index);
		}
		else if (op == 2) {
			int index_to_remove;
			ifs >> index_to_remove;
			heap_.remove(index_to_remove - 1);
		}
		else { //op == 3
			//write the minimum to file
			ofs << heap_(0) << endl;
		}
	}
	ofs.close();
	ifs.close();


	return 0;
}