Cod sursa(job #1071644)

Utilizator dm1sevenDan Marius dm1seven Data 3 ianuarie 2014 11:50:29
Problema Statistici de ordine Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.94 kb
#include <fstream>
using namespace std;

namespace e_041_sdo_heap
{
	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);
		}

		void replace(int position, T new_val, int new_index)
		{
			//optional, not implemented: reset the old position

			a[position] = new_val;
			positions[new_index] = position;
			indexes[position] = new_index;

			//update the heap
			update_position(position);
		}

	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;
				}
			}
		}

		inline 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 sdo_heap()
int main()
{
	string in_file = "sdo.in";
	string out_file = "sdo.out";

	int N, K;
	const int MAX_K = 3000000;
	
	e_041_sdo_heap::heap<int, MAX_K> heap_;
	ifstream ifs(in_file);
	ifs >> N >> K;
	int x;
	ifs >> x;
	int ind_heap = 0;
	heap_.insert(x, ind_heap++);

	for (int i = 0; i < N; i++) {
		int x;
		ifs >> x;
		if (ind_heap < K) heap_.insert(x, ind_heap++);
		else if (x < heap_(0)) heap_.replace(0, x, ind_heap++);
	}
	ifs.close();

	ofstream ofs(out_file);
	ofs << heap_(0);
	ofs.close();

	return 0;
}