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 JAVA (judge verdict: Accepted)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

public class Main {
	
	public static int MergeSort(final int[] A, final int left, final int right){ //[left, right)		
		if(left + 1 < right){
			final int mid = (left + right) / 2;
			
			int ret = 0;
			ret += MergeSort(A, left, mid);
			ret += MergeSort(A, mid, right);
			
			final int l_size = mid - left;
			final int r_size = right - mid;
			final int size = l_size + r_size;
			int[] ls = new int[l_size + 1];
			ls[l_size] = Integer.MAX_VALUE;
			for(int i = 0; i < l_size; i++){
				ls[i] = A[left + i];
			}
			int[] rs = new int[r_size + 1];
			rs[r_size] = Integer.MAX_VALUE;
			for(int i = 0; i < r_size; i++){
				rs[i] = A[mid + i];
			}
			
			int l_pos = 0, r_pos = 0;
			int count = 0;
			while(count < size){
				if(ls[l_pos] <= rs[r_pos]){
					A[left + count] = ls[l_pos];
					l_pos++;
				}else{
					A[left + count] = rs[r_pos];
					r_pos++;
				}
				ret++;
				count++;
			}
			
			return ret;
		}
		
		return 0;
	}
	
	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
		
		final int n = sc.nextInt();
		int[] array = new int[n];
		for(int i = 0; i < n; i++){
			array[i] = sc.nextInt();
		}
		
		final int ret = MergeSort(array, 0, array.length);
		
		for(int i = 0; i < n; i++){
			if(i != 0){
				System.out.print(" ");
			}
			System.out.print(array[i]);
		}
		System.out.println();
		System.out.println(ret);
	}
	
	public static class Scanner {
	    private BufferedReader br;
	    private StringTokenizer tok;

	    public Scanner(InputStream is) throws IOException {
	        br = new BufferedReader(new InputStreamReader(is));
	    }

	    private void getLine() throws IOException {
	        while (!hasNext()) { tok = new StringTokenizer(br.readLine()); }
	    }

	    private boolean hasNext() {
	        return tok != null && tok.hasMoreTokens();
	    }

	    public String next() throws IOException {
	        getLine(); return tok.nextToken();
	    }

	    public int nextInt() throws IOException {
	        return Integer.parseInt(next());
	    }
	    
	    public long nextLong() throws IOException {
	    	return Long.parseLong(next());
	    }
	    
	    public void close() throws IOException {
	        br.close();
	    }
	}

}