Cod sursa(job #457778)

Utilizator tomescu_alinTomescu Alin tomescu_alin Data 21 mai 2010 15:29:52
Problema Statistici de ordine Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.36 kb
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <fstream>

using namespace std;

typedef unsigned long ulong;

ulong partition(ulong a[], ulong low, ulong high, ulong pivot)
{
	/**
	 *	All the elements before the leftbound index (exclusive) are less than the pivot.
	 *	We will increase this leftbound index as we find elements that are less than the
	 *	pivot.
	 *
	 *	The trick is we go past elements that are greater than the pivot leaving them where
	 *	they are. These bigger elements will get swapped with smaller elements whenever the 
	 *	leftwall is advanced.
	 */
	ulong leftbound = low;
	
	/**
	 *	We will move the pivot onto the first position.
	 */
	swap(a[low], a[pivot]);
	ulong& pivotValue = a[low];
	
	/**
	 *	For the remaining elements, advance the leftwall as you find elements
	 *	smaller than the pivot. When you find bigger elements than the pivot 
	 *	leave them into place. They will later get swapped with smaller elements
	 *	as the leftwall advances.
	 */
	for(ulong i = low + 1; i < high; i++)
	{
		if(a[i] < pivotValue)
		{
			leftbound++;
			swap(a[i], a[leftbound]);
		}
	}
	
	/**
	 *	Finally put the pivot where it belongs.
	 */
	swap(a[leftbound], a[low]);
	
	return leftbound;
}

ulong kth_smallest_helper_recursive(ulong a[], ulong k, ulong low, ulong high)
{
	/**
	 *	Get a random pivot in [low, high) range.
	 */
	ulong pivot = (rand() % (high - low)) + low;
	
	/**
	 *	Partition the array around the pivot, left <= pivot <= right.
	 */
	pivot = partition(a, low, high, pivot);
	
	/**
	 *	If we got lucky and the pivot turned up on the kth position then
	 *	we found the kth smallest element.
	 */
	if(pivot == k)
	{
		return a[pivot];
	}
	/**
	 *	If we didn't get lucky, we can either way just look on one side of
	 *	the pivot for the kth element, depending on where the pivot ended up
	 *	relative to k.
	 */
	else if(k < pivot)
	{
		return kth_smallest_helper_recursive(a, k, low, pivot);
	}
	else
	{
		return kth_smallest_helper_recursive(a, k, pivot + 1, high);
	}
}


ulong kth_smallest_helper(ulong a[], ulong k, ulong low, ulong high)
{
	ulong pivot;
	
	/**
	 *	If we got lucky and the pivot turned up on the kth position then
	 *	we found the kth smallest element.
	 */
	do
	{
		/**
		 *	Get a random pivot in [low, high) range.
		 */
		pivot = (rand() % (high - low)) + low;
		
		/**
		 *	Partition the array around the pivot, left <= pivot <= right.
		 */
		pivot = partition(a, low, high, pivot);
		
		/**
		 *	If we didn't get lucky, we can look on one side of the pivot for 
		 *	the kth element, depending on where the pivot ended up relative to k.
		 */
		if(k < pivot)
		{
			high = pivot;
		}
		else
		{
			low = pivot + 1;
		}
	} while(pivot != k);
	
	return a[pivot];
}

ulong kth_smallest(ulong a[], ulong k, ulong length)
{
	return kth_smallest_helper(a, k, 0, length);
}

int main()
{	
	const char * inFile = "sdo.in";
	const char * outFile = "sdo.out";
	
	ifstream fin(inFile);
	ofstream fout(outFile);
	
	/**
	 *	Read the data in.
	 */
	ulong n, k;
	fin >> n >> k;
	
	ulong * a = new ulong[n];
	
	for(ulong i = 0; i < n; i++)
		fin >> a[i];
	
	fin.close();
	
	/**
	 *	Write out the result.
	 */
	fout << kth_smallest(a, k - 1, n);
	fout.close();
	
	delete [] a;
	
	return 0;
}