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# (.NET Core 3.1.201) (judge verdict: Wrong Answer)

using System;
using System.Collections.Generic;
using static Assistant.Input;
using static Assistant.Debug;
using System.Linq;
using Assistant;

namespace ARC074D
{
    class Program
    {
        static void Main(string[] args)
        {
            var N = RInt;
            var A = RInts;

            Set<int> setFirst = new Set<int>(true); // なるべく大きいもの
            Set<int> setLast = new Set<int>(true);  // なるべく小さいもの
            long sumFirst = 0;
            long sumLast = 0;
            for (int i = 0; i < N; i++)
            {
                setFirst.Add(A[i]);
                sumFirst += A[i];
            }
            for (int i = 2 * N; i < 3 * N; i++)
            {
                setLast.Add(A[i]);
                sumLast += A[i];
            }

            long[] sumF = new long[N + 1];
            long[] sumL = new long[N + 1];
            sumF[0] = sumFirst;
            sumL[N] = sumLast;

            for (int i = N; i < 2 * N; i++)
            {
                setFirst.Add(A[i]);
                sumFirst += A[i];
                sumFirst -= setFirst.Min;
                sumF[i - N + 1] = sumFirst;
                setFirst.Remove(setFirst.Min);
            }
            for (int i = 2 * N - 1; i >= N; i--)
            {
                setLast.Add(A[i]);
                sumLast += A[i];
                sumLast -= setLast.Max;
                sumL[i - N] = sumLast;
                setLast.Remove(setLast.Max);
            }
            Draw1D(sumF);
            Draw1D(sumL);

            long ans = long.MinValue;
            for (int i = 0; i < N; i++)
            {
                long cand = sumF[i] - sumL[i];
                ans = Math.Max(ans, cand);
            }

            Console.WriteLine(ans);
        }


    }

    public class Set<T>
    {
        Node root;
        readonly IComparer<T> comparer;
        readonly Node nil;
        public bool IsMultiSet { get; set; }
        public Set(IComparer<T> comparer)
        {
            nil = new Node(default(T));
            root = nil;
            this.comparer = comparer;
        }
        public Set(Comparison<T> comparison) : this(Comparer<T>.Create(comparison)) { }
        public Set() : this(Comparer<T>.Default) { }
        public Set(bool isMultiSet) : this(Comparer<T>.Default) { IsMultiSet = isMultiSet; }
        public bool Add(T v)
        {
            return insert(ref root, v);
        }
        public bool Remove(T v)
        {
            return remove(ref root, v);
        }
        public T this[int index] { get { return find(root, index); } }
        public T Min { get { return this[0]; } }
        public T Max { get { return this[Count - 1]; } }
        public int Count { get { return root.Count; } }
        public void RemoveAt(int k)
        {
            if (k < 0 || k >= root.Count) throw new ArgumentOutOfRangeException();
            removeAt(ref root, k);
        }
        public T[] Items
        {
            get
            {
                var ret = new T[root.Count];
                var k = 0;
                walk(root, ret, ref k);
                return ret;
            }
        }
        void walk(Node t, T[] a, ref int k)
        {
            if (t.Count == 0) return;
            walk(t.lst, a, ref k);
            a[k++] = t.Key;
            walk(t.rst, a, ref k);
        }

        bool insert(ref Node t, T key)
        {
            if (t.Count == 0) { t = new Node(key); t.lst = t.rst = nil; t.Update(); return true; }
            var cmp = comparer.Compare(t.Key, key);
            bool res;
            if (cmp > 0)
                res = insert(ref t.lst, key);
            else if (cmp == 0)
            {
                if (IsMultiSet) res = insert(ref t.lst, key);
                else return false;
            }
            else res = insert(ref t.rst, key);
            balance(ref t);
            return res;
        }
        bool remove(ref Node t, T key)
        {
            if (t.Count == 0) return false;
            var cmp = comparer.Compare(key, t.Key);
            bool ret;
            if (cmp < 0) ret = remove(ref t.lst, key);
            else if (cmp > 0) ret = remove(ref t.rst, key);
            else
            {
                ret = true;
                var k = t.lst.Count;
                if (k == 0) { t = t.rst; return true; }
                if (t.rst.Count == 0) { t = t.lst; return true; }


                t.Key = find(t.lst, k - 1);
                removeAt(ref t.lst, k - 1);
            }
            balance(ref t);
            return ret;
        }
        void removeAt(ref Node t, int k)
        {
            var cnt = t.lst.Count;
            if (cnt < k) removeAt(ref t.rst, k - cnt - 1);
            else if (cnt > k) removeAt(ref t.lst, k);
            else
            {
                if (cnt == 0) { t = t.rst; return; }
                if (t.rst.Count == 0) { t = t.lst; return; }

                t.Key = find(t.lst, k - 1);
                removeAt(ref t.lst, k - 1);
            }
            balance(ref t);
        }
        void balance(ref Node t)
        {
            var balance = t.lst.Height - t.rst.Height;
            if (balance == -2)
            {
                if (t.rst.lst.Height - t.rst.rst.Height > 0) { rotR(ref t.rst); }
                rotL(ref t);
            }
            else if (balance == 2)
            {
                if (t.lst.lst.Height - t.lst.rst.Height < 0) rotL(ref t.lst);
                rotR(ref t);
            }
            else t.Update();
        }

        T find(Node t, int k)
        {
            if (k < 0 || k > root.Count) throw new ArgumentOutOfRangeException();
            for (; ; )
            {
                if (k == t.lst.Count) return t.Key;
                else if (k < t.lst.Count) t = t.lst;
                else { k -= t.lst.Count + 1; t = t.rst; }
            }
        }
        public int LowerBound(T v)
        {
            var k = 0;
            var t = root;
            for (; ; )
            {
                if (t.Count == 0) return k;
                if (comparer.Compare(v, t.Key) <= 0) t = t.lst;
                else { k += t.lst.Count + 1; t = t.rst; }
            }
        }
        public int UpperBound(T v)
        {
            var k = 0;
            var t = root;
            for (; ; )
            {
                if (t.Count == 0) return k;
                if (comparer.Compare(t.Key, v) <= 0) { k += t.lst.Count + 1; t = t.rst; }
                else t = t.lst;
            }
        }

        void rotR(ref Node t)
        {
            var l = t.lst;
            t.lst = l.rst;
            l.rst = t;
            t.Update();
            l.Update();
            t = l;
        }
        void rotL(ref Node t)
        {
            var r = t.rst;
            t.rst = r.lst;
            r.lst = t;
            t.Update();
            r.Update();
            t = r;
        }


        class Node
        {
            public Node(T key)
            {
                Key = key;
            }
            public int Count { get; private set; }
            public sbyte Height { get; private set; }
            public T Key { get; set; }
            public Node lst, rst;
            public void Update()
            {
                Count = 1 + lst.Count + rst.Count;
                Height = (sbyte)(1 + Math.Max(lst.Height, rst.Height));
            }
            public override string ToString()
            {
                return string.Format("Count = {0}, Key = {1}", Count, Key);
            }
        }
    }
}

namespace Assistant
{
    static class Input
    {
        static List<string> line = new List<string>();
        static int index = 0;
        static String RNext()
        {
            if (line.Count <= index) line.AddRange(Console.ReadLine().Split());
            return line[index++];
        }
        public static int RInt => int.Parse(RNext());
        public static long RLong => long.Parse(RNext());
        public static int[] RInts => Console.ReadLine().Split().Select(int.Parse).ToArray();
        public static long[] RLongs => Console.ReadLine().Split().Select(long.Parse).ToArray();
        public static string RString => RNext();
        //以下未テスト
        public static int[] RIntsC(int c) => Enumerable.Repeat(0, c).Select(x => int.Parse(RNext())).ToArray();
        public static long[] RLongsC(int c) => Enumerable.Repeat(0, c).Select(x => long.Parse(RNext())).ToArray();
        public static char[][] RMap(int h) => Enumerable.Repeat(0, h).Select(x => Console.ReadLine().ToCharArray()).ToArray();
    }

    public struct Mlong
    {
        long _v;
        const long mod = 1000000007;
        public Mlong(long n = 0) : this() { _v = n >= mod ? n % mod : n; }

        public static implicit operator Mlong(long _x) => new Mlong(_x);
        public static implicit operator long(Mlong _x) => _x._v;
        public static Mlong operator +(Mlong m1, Mlong m2) { long m = m1._v + m2._v; return m >= mod ? m - mod : m; }
        public static Mlong operator -(Mlong m1, Mlong m2) { long m = m1._v - m2._v; return m >= 0 ? m : m + mod; }
        public static Mlong operator *(Mlong m1, Mlong m2) => m1._v * m2._v % mod;
        public static Mlong operator /(Mlong m1, Mlong m2) => m1._v * ModPow(m2._v, mod - 2) % mod;

        public static long ModPow(long a, long n)
        {
            if (n == 0) return 1;
            else if (n % 2 == 1) return a * ModPow(a, n - 1) % mod;
            else return ModPow(a * a % mod, n / 2);
        }

        static Mlong[] fac, finv, inv;
        public static void nCkInit(int max)
        {
            fac = new Mlong[max]; finv = new Mlong[max]; inv = new Mlong[max];
            fac[0] = fac[1] = 1;
            finv[0] = finv[1] = 1;
            inv[1] = 1;
            for (int i = 2; i < max; i++)
            {
                fac[i] = fac[i - 1] * i;
                inv[i] = mod - inv[mod % i] * (mod / i);
                finv[i] = finv[i - 1] * inv[i];
            }
        }

        public static Mlong nCk(int n, int k)
        {
            if (n < k) return 0;
            if (n < 0 || k < 0) return 0;
            return fac[n] * finv[k] * finv[n - k];
        }
    }

    static class Debug
    {
        static public void Draw2D<T>(T[,] map, int mode = 1)
        {
#if DEBUG
            int W = map.GetLength(0);
            int H = map.GetLength(1);

            string[,] map2 = new string[W + 1, H + 1];
            for (int i = 0; i < W + 1; i++)
            {
                for (int j = 0; j < H + 1; j++)
                {
                    if (i == 0 && j == 0) map2[i, j] = 0.ToString();
                    else if (i == 0) map2[i, j] = (j - 1).ToString();
                    else if (j == 0) map2[i, j] = (i - 1).ToString();
                    else map2[i, j] = map[i - 1, j - 1].ToString();
                }
            }

            for (int i = 0; i < W + 1; i++)
            {
                for (int j = 0; j < H + 1; j++)
                {
                    if (mode == 0) Console.Write(map2[i, j].Last());
                    if (mode == 1) Console.Write(map2[i, j] + " ");
                }
                Console.WriteLine();
            }
            Console.WriteLine();
#endif
        }

        public static void Draw1D<T>(T[] array, int mode = 0)
        {
#if DEBUG
            Console.WriteLine(string.Join(" ", array));
#endif
        }
    }
}