Problem:
Score : 500 points

Problem Statement

Let N be a positive integer.

There is a numerical sequence of length 3N, a = (a_1, a_2, ..., a_{3N}).
Snuke is constructing a new sequence of length 2N, a', by removing exactly N elements from a without changing the order of the remaining elements.
Here, the score of a' is defined as follows: (the sum of the elements in the first half of a') - (the sum of the elements in the second half of a').

Find the maximum possible score of a'.

Constraints

1 ≤ N ≤ 10^5

a_i is an integer.

1 ≤ a_i ≤ 10^9

Partial Score

In the test set worth 300 points, N ≤ 1000.

Input

Input is given from Standard Input in the following format:

N
a_1 a_2 ... a_{3N}

Output

Print the maximum possible score of a'.

Sample Input 1

2
3 1 4 1 5 9

Sample Output 1

1

When a_2 and a_6 are removed, a' will be (3, 4, 1, 5), which has a score of (3 + 4) - (1 + 5) = 1.

Sample Input 2

1
1 2 3

Sample Output 2

-1

For example, when a_1 are removed, a' will be (2, 3), which has a score of 2 - 3 = -1.

Sample Input 3

3
8 2 2 7 4 6 5 3 8

Sample Output 3

5

For example, when a_2, a_3 and a_9 are removed, a' will be (8, 7, 4, 6, 5, 3), which has a score of (8 + 7 + 4) - (6 + 5 + 3) = 5.

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

using System;
using System.Linq;//リストの使用
using System.Collections.Generic;
class Program
{
static int n = int.Parse(Console.ReadLine());//int.Parseは文字列を整数に変換。
static long[] nums = Array.ConvertAll(Console.ReadLine().Split(' '),long.Parse);
static List<long> numsThree = new List<long>();
static List<long> numsThreeR = new List<long>();
static long[] sum = new long[n+1];
static long[] sumR = new long[n+1];
static long answer = 0;
static long check = 0;

	static void Main()
	{
      
    for(int i=0; i<n; i++)
    {
    sum[0] += nums[i];
    numsThree.Add(nums[i]);
    
    sumR[n] += nums[3*n-1-i];
    numsThreeR.Add(nums[3*n-1-i]);
    }
    
    

    //numsThree.Sort();//昇順にソート
    //numsThreeR.Sort();//降順にソート
    //numsThreeR.Reverse();

      
    for(int i=0; i<n; i++)
    {
      numsThree = PushHeap(numsThree,nums[n+i]);
      sum[i+1] = sum[i] + nums[n+i];
      numsThree = PopHeap(numsThree);
      sum[i+1] -= check;

      numsThreeR = PushHeapR(numsThreeR,nums[2*n-1-i]);
      sumR[n-1-i] = sumR[n-i] + nums[2*n-1-i];
      numsThreeR = PopHeapR(numsThreeR);
      sumR[n-1-i] -= check;
    }
    
    answer = sum[0] - sumR[0];
    //Console.WriteLine(sum[0] +" "+ sumR[0]);//デバッグ
    for(int i=1; i<=n; i++)
    {
      long ans = sum[i] - sumR[i];
      //Console.WriteLine(sum[i] +" "+ sumR[i]);//デバッグ
      if(ans > answer) answer = ans;
    }
    
	Console.WriteLine(answer);
	}

  static List<long> PushHeap(List<long> nums, long addNum)//現在のヒープnumsにaddNumを追加
{
  int n = nums.Count;
  nums.Add(addNum);

  while (n > 0)
  {
    int i = (n-1)/2;
    if (nums[n] < nums[i])//親のほうが大きいなら入れ替え。
    {
      long tmp = nums[n];
      nums[n] = nums[i];
      nums[i] = tmp;
    }
    n = i;
  }
  return nums;
}

static List<long> PopHeap(List<long> nums)//ヒープnumsからポップ
{
  int n = nums.Count - 1;
  check = nums[0];
  nums[0] = nums[n];//最大値である根を削除して配列の最後を持ってくる
  nums.RemoveAt(n);

  for (int i = 0, j; (j = 2*i+1) < n; )
  {
    if ((j != n-1) && (nums[j] > nums[j+1]))// ２つの子のうち、値の小さい方を選ぶ
      j++;
    if (nums[i] > nums[j])//子が親より小さいなら入れ替え
    {
      long tmp = nums[j];
      nums[j] = nums[i];
      nums[i] = tmp;
    }
    i = j;
  }
  return nums;
}

static List<long> PushHeapR(List<long> nums, long addNum)//現在のヒープnumsにaddNumを追加
{
  int n = nums.Count;
  nums.Add(addNum);

  while (n > 0)
  {
    int i = (n-1)/2;
    if (nums[n] > nums[i])//親のほうが小さいなら入れ替え。
    {
      long tmp = nums[n];
      nums[n] = nums[i];
      nums[i] = tmp;
    }
    n = i;
  }
  return nums;
}

static List<long> PopHeapR(List<long> nums)//ヒープnumsからポップ
{
  int n = nums.Count - 1;
  check = nums[0];
  nums[0] = nums[n];//最大値である根を削除して配列の最後を持ってくる
  nums.RemoveAt(n);

  for (int i = 0, j; (j = 2*i+1) < n; )
  {
    if ((j != n-1) && (nums[j] < nums[j+1]))// ２つの子のうち、値の大きい方を選ぶ
      j++;
    if (nums[i] < nums[j])//子が親より大きいなら入れ替え
    {
      long tmp = nums[j];
      nums[j] = nums[i];
      nums[i] = tmp;
    }
    i = j;
  }
  return nums;
}




  
}