Cod sursa(job #1077622)

Utilizator dm1sevenDan Marius dm1seven Data 11 ianuarie 2014 15:22:05
Problema Statistici de ordine Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 3.19 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 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]; }
		
		int size() { return N; }

		void insert(T x)
		{
			a[N++] = x;
			update_position(N - 1);
		}

		void remove(int position)
		{			
			exchange_positions(position, N - 1); //exchange with the last element			
			N--; //remove the last element		
			update_position(position); //update the heap
		}

		void replace(int position, int new_val)
		{
			a[position] = new_val;
			update_position(position);
		}

	private:

		/**
		* Update the heap if the element at the given position has changed its value.
		* 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 child with the maximum value
					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;
		}
	};
}

//int sdo_heap_minimal()
int main()
{
	string in_file = "sdo.in";
	string out_file = "sdo.out";

	int N, K;
	const int MAX_K = 300000;

	e_041_sdo_heap::heap<int, MAX_K> heap_;
	ifstream ifs(in_file);
	ifs >> N >> K;
	int x;
	ifs >> x;
	heap_.insert(x);

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

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

	return 0;
}