Problem:
Score : 500 points

Problem Statement

There are N integers, A_1, A_2, ..., A_N, written on a blackboard.

We will repeat the following operation N-1 times so that we have only one integer on the blackboard.

Choose two integers x and y on the blackboard and erase these two integers. Then, write a new integer x-y.

Find the maximum possible value of the final integer on the blackboard and a sequence of operations that maximizes the final integer.

Constraints

2 \leq N \leq 10^5

-10^4 \leq A_i \leq 10^4

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
A_1 A_2 ... A_N

Output

Print the maximum possible value M of the final integer on the blackboard, and a sequence of operations x_i, y_i that maximizes the final integer, in the format below.

Here x_i and y_i represent the integers x and y chosen in the i-th operation, respectively.

If there are multiple sequences of operations that maximize the final integer, any of them will be accepted.

M
x_1 y_1
:
x_{N-1} y_{N-1}

Sample Input 1

3
1 -1 2

Sample Output 1

4
-1 1
2 -2

If we choose x = -1 and y = 1 in the first operation, the set of integers written on the blackboard becomes (-2, 2).

Then, if we choose x = 2 and y = -2 in the second operation, the set of integers written on the blackboard becomes (4).

In this case, we have 4 as the final integer. We cannot end with a greater integer, so the answer is 4.

Sample Input 2

3
1 1 1

Sample Output 2

1
1 1
1 0

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Text;
using System.Linq;
using System.Collections;
using System.Collections.Generic;


class Program {

	static long mod = 998244353;
	static int[] ans;
	static void Main(string[] args) {

		char[] cs = new char[] { ' ' };
		//char[] cs = new char[] { ' ', ',' };

		//int n = int.Parse(Console.ReadLine());
		//int val = int.Parse(Console.ReadLine());
		//int[] vals = parseAry(Console.ReadLine().Split(cs));
		//string str = Console.ReadLine();
		//string[] strs = Console.ReadLine().Split(cs);

		//string res="";
		int res = 0;

		int n = int.Parse(Console.ReadLine());
		
		int[] nums = parseAry(Console.ReadLine().Split(cs));


		PriorityQueue pq = new PriorityQueue();

		for ( int i = 0; i < n; i++ ) {
			pq.Enqueue(new PriQ() { rank =nums[i]});
		}
		int flg = 1;
		if ( n % 2 == 1 ) { flg = -1; }

		string[] output=new string[n-1];
		int a = 0;
		while ( pq.Count > 1 ) {
			int low = pq.Dequeue().rank;
			int hei = pq.DequeueLast().rank;
			int c=0;
			if ( flg == 1 ) { c = hei - low; output[a] = "" + hei + " " + low; } 
			else { c = low - hei; output[a] = "" + low + " " + hei; }
			pq.Enqueue(new PriQ() { rank = c });
			flg *= -1;
			a++;
		}
		res = pq.Dequeue().rank;
			Console.WriteLine(res);
			for ( int i = 0; i < n - 1;i++ ){
			Console.WriteLine(output[i]);
			
			}

				return;

	}




	//	文字列strをindex番目からdで上書き
	static string strOverWrite(string str, int i, string s) {
		return str.Remove(i, s.Length).Insert(i, s);
	}

	//　String[]  ----->  int[]
	static int[] parseAry(string[] str) {
		int[] nums = new int[str.Length];
		for ( int i = 0; i < str.Length; i++ ) { nums[i] = int.Parse(str[i]); }
		return nums;
	}
	//　String[]  ----->  long[]
	static long[] parseAryL(string[] str) {
		long[] nums = new long[str.Length];
		for ( int i = 0; i < str.Length; i++ ) { nums[i] = long.Parse(str[i]); }
		return nums;
	}

	//文字列を1文字ずつString[]に入れる
	static string[] strAry(String str) {
		string[] re = new string[str.Length];
		for ( int i = 0; i < str.Length; i++ ) { re[i] = str[i].ToString(); }
		return re;
	}


	public class PriQ {
		public int rank { get; set; }
		public string rankstr { get; set; }
		public int num { get; set; }
		public int[] nums { get; set; }
		public Object obj { get; set; }
		public PriQ() { }
	}

	public class PriorityQueue {
		List<PriQ> list = new List<PriQ>();
		public PriorityQueue() { }
		public PriorityQueue(PriQ p) { list.Add(p); }
		public void Enqueue(PriQ item) { list.Insert(Binary_Search(item), item); }
		public PriQ Dequeue() { PriQ r = list[0]; list.RemoveAt(0); return r; }
		public PriQ DequeueLast() { PriQ r = list[list.Count - 1]; list.RemoveAt(list.Count - 1); return r; }
		public PriQ Peek() { return list[0]; }
		public PriQ Get(int n) { return list[n]; }
		public PriQ Last() { return list[list.Count - 1]; }
		public void Remove(int n) { list.RemoveAt(n); }
		public void Clear() { list.Clear(); }
		public int Count { get { return list.Count; } }

		private int Binary_Search(PriQ pq) {
			int Lower = 0;
			int Upper = list.Count - 1;
			while ( Lower <= Upper ) {
				int Center = ( Lower + Upper ) >> 1;
				if ( pq.rank > list[Center].rank ) {
					Lower = Center + 1;
				} else if ( pq.rank < list[Center].rank ) {
					Upper = Center - 1;
				} else {
					return Center;
				}
			}
			return Lower;
		}
	}
}