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: Runtime Error)

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

namespace ConsoleApp15
{
    class Class365
    {
        static void Main()
        {
            int N = int.Parse(Console.ReadLine());
            var A = Array.ConvertAll(Console.ReadLine().Split(), long.Parse);
            var a = new PriorityQueue<long>(N, (x, y) => x.CompareTo(y));
            var b = new List<long>();
            var c = new PriorityQueue<long>(N, (x, y) => -x.CompareTo(y));
            for (int i = 0; i < N; i++)
                a.Push(A[i]);
            for (int i = N; i < 2 * N; i++)
                b.Add(A[i]);
            for (int i = 2 * N; i < 3 * N; i++)
                c.Push(A[i]);

            var L = new long[N + 1];
            var R = new long[N + 1];
            L[0] = 0;
            R[0] = 0;
            long suma = a.m_heap.Sum();
            long sumc = c.m_heap.Sum();
            for(int i = 0; i < N; i++)
            {
                var d = a.Pop();
                if (b[i] > d)
                {
                    L[i + 1] = L[i] + b[i] - d;
                    a.Push(b[i]);
                }
                else a.Push(d);
            }
            for(int i = 0; i < N; i++)
            {
                var e = c.Pop();
                if (b[N - i - 1] < e)
                {
                    R[i + 1] = R[0] + e - b[N - i - 1];
                    c.Push(b[N - i - 1]);
                }
                else c.Push(e);
            }
            long p = 0;
            for(int i = 0; i < N+1; i++)
            {
                p = Math.Max(L[i] + R[N - i-1], p);
            }
            Console.WriteLine(suma-sumc+p);
        }
    }
    //初期化は (Size ,(x,y)=>x.compareto(y)) 比較演算子で比較している
    public class PriorityQueue<T>
    {
        public long Size { get; private set; } = 0;
        public long MaxSize { get; private set; } = 0;
        public T[] m_heap;
        private Comparison<T> Comp = null;

        public PriorityQueue(long maxSize, Comparison<T> comp)
        {
            if (maxSize <= 0)
                throw new Exception();
            MaxSize = maxSize;
            m_heap = new T[maxSize];

            Comp = comp;
        }

        public void Push(T x)
        {
            if (Size == MaxSize)
            {
                T[] new_heap = new T[MaxSize << 1];
                Array.Copy(m_heap, new_heap, MaxSize);
                m_heap = new_heap;
                MaxSize <<= 1;
            }

            long i = Size++;
            while (i > 0)
            {
                long p = (i - 1) / 2;
                if (Comp(m_heap[p], x) <= 0)
                    break;
                m_heap[i] = m_heap[p];
                i = p;
            }
            m_heap[i] = x;
        }

        public T Pop()
        {
            if (Size == 0)
                throw new Exception("Queue is empty.");

            T result = m_heap[0];
            T x = m_heap[--Size];
            long i = 0;
            while (i * 2 + 1 < Size)
            {
                long c1 = i * 2 + 1, c2 = i * 2 + 2;
                if (c2 < Size && Comp(m_heap[c2], m_heap[c1]) < 0)
                    c1 = c2;
                if (Comp(m_heap[c1], x) >= 0)
                    break;
                m_heap[i] = m_heap[c1];
                i = c1;
            }
            m_heap[i] = x;

            return result;
        }
    }
}