Problem:
Merge Sort

Write a program of a Merge Sort algorithm implemented by the following pseudocode. You should also report the number of comparisons in the Merge function.

Merge(A, left, mid, right)
n1 = mid - left;
n2 = right - mid;
create array L[0...n1], R[0...n2]
for i = 0 to n1-1
do L[i] = A[left + i]
for i = 0 to n2-1
do R[i] = A[mid + i]
L[n1] = SENTINEL
R[n2] = SENTINEL
i = 0;
j = 0;
for k = left to right-1
if L[i] <= R[j]
then A[k] = L[i]
i = i + 1
else A[k] = R[j]
j = j + 1

Merge-Sort(A, left, right){
if left+1 < right
then mid = (left + right)/2;
call Merge-Sort(A, left, mid)
call Merge-Sort(A, mid, right)
call Merge(A, left, mid, right)

Input

In the first line n is given. In the second line, n integers are given.

Output

In the first line, print the sequence S. Two consequtive elements should be separated by a space character.

In the second line, print the number of comparisons.

Constraints

n ≤ 500000

0 ≤ an element in S ≤ 109

Sample Input 1

10
8 5 9 2 6 3 7 1 10 4

Sample Output 1

1 2 3 4 5 6 7 8 9 10
34

Notes

Solution in C# (judge verdict: Accepted)

using System;
using System.Linq;

namespace ALDS1_5_B_MergeSort
{
	class Program
	{
		static void Main ( string[] args )
		{
			int dataCount = int.Parse (Console.ReadLine ());
			int[] numArray = Console.ReadLine ().Split (' ').Select (int.Parse).ToArray ();

			MergeSort (numArray);

			for (int lp = 0; lp < dataCount - 1; lp++)
			{
				Console.Write (numArray[lp] + " ");
			}
			Console.WriteLine (numArray[dataCount - 1]);
			Console.WriteLine (Count);
		}

		static int Count = 0;

		static void MergeSort ( int[] numArray )
		{
			MergeSort (numArray, 0, numArray.Length);
		}

		static void MergeSort ( int[] numArray, int leftIndex, int rightIndex )
		{
			//3?????\??????????´????????????¨???
			//0~1 ??
			//0~2 ???
			if (leftIndex + 1 < rightIndex)
			{
				int middleIndex = (leftIndex + rightIndex) / 2;
				MergeSort (numArray, leftIndex, middleIndex);
				MergeSort (numArray, middleIndex, rightIndex);
				Merge (numArray, leftIndex, middleIndex, rightIndex);
			}
		}

		static void Merge ( int[] numArray, int leftIndex, int middleIndex, int rightIndex )
		{
			int n1 = middleIndex - leftIndex;
			int n2 = rightIndex - middleIndex;

			int[] leftArray = new int[n1 + 1];
			int[] rightArray = new int[n2 + 1];

			for (int index = 0; index < n1; index++)
			{
				leftArray[index] = numArray[leftIndex + index];
			}
			for (int index = 0; index < n2; index++)
			{
				rightArray[index] = numArray[middleIndex + index];
			}

			//sentinel
			leftArray[n1] = int.MaxValue;
			rightArray[n2] = int.MaxValue;

			int left = 0;
			int right = 0;

			for (int index = leftIndex; index < rightIndex; index++)
			{
				Count++;

				if (leftArray[left] <= rightArray[right])
				{
					numArray[index] = leftArray[left];
					left++;
				}
				else
				{
					numArray[index] = rightArray[right];
					right++;
				}
			}
		}
	}
}