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 (GCC 5.4.1) (judge verdict: Wrong Answer)

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

#define llong long long
#define fr(i,l,r) for(i=(l);i<(r);i++)
#define min(p,q) ((p)<(q)?(p):(q))
#define max(p,q) ((p)>(q)?(p):(q))

static long int heap[100010];
int sz=-1;

void push(long int x){
	//自分のノード番号
	int i;
	int p;
	sz++;
	i=sz;
	
	while(i>0){
		//親のノード番号
		p=(i-1)/2;
		//もう逆転していないなら抜ける
		if(heap[p]<=x) break;
		//親のノードの数字を下ろして、自分は上に
		heap[i]=heap[p];
		i=p;
	}
	heap[i]=x;
}

int pop(){
	long int ret;
	int a,b;
	long int x;
	int i;
	//最小値
	ret=heap[0];
	//根に持ってくる値
	x=heap[sz];
	sz=sz-1;
	//根からおろしていく
	i=0;
	while(i*2+1<=sz){
		a=i*2+1;
		b=i*2+2;
		if(b<=sz&&heap[b]<heap[a]) a=b;
		//もう逆転していないなら終わり
		if(heap[a]>=x) break;
		//子の数字を持ち上げる
		heap[i]=heap[a];
		i=a;
	}
	heap[i]=x;
	
	return ret;
}

static long int heapup[100010];
int szup=-1;

void pushup(long int x){
	//自分のノード番号
	int i;
	int p;
	szup++;
	i=szup;
	
	while(i>0){
		//親のノード番号
		p=(i-1)/2;
		//もう逆転していないなら抜ける
		if(heapup[p]>=x) break;
		//親のノードの数字を下ろして、自分は上に
		heapup[i]=heapup[p];
		i=p;
	}
	heapup[i]=x;
}

int popup(){
	long int ret;
	int a,b;
	long int x;
	int i;
	//最小値
	ret=heapup[0];
	//根に持ってくる値
	x=heapup[szup];
	szup=szup-1;
	//根からおろしていく
	i=0;
//	printf("szup=%d\n",szup);
	while(i*2+1<=szup){
		a=i*2+1;
		b=i*2+2;
//		printf("a=%d\n",a);
		if(b<=szup&&heapup[b]>heapup[a]) a=b;
		//もう逆転していないなら終わり
		if(heapup[a]<=x) {
//			printf("a=%d break;\n",a);
			break;
		}
		//子の数字を持ち上げる
		heapup[i]=heapup[a];
		i=a;
	}
	heapup[i]=x;
	
	return ret;
}



int main(void)
{
	//変数の宣言
	int n;
	static llong int a[100010];
	static llong int lsum[100010];
	static llong int ldec[100010];
	static llong int rsum[100010];
	static llong int rdec[100010];
	
	//よく使う変数
	int i,j,k,l;
	int flag=0;
	llong int ans=0;
	int count=0;
	llong int temp,temp1,temp2;
	int max,min;
	int len;
	//データの読み込み
	
	scanf("%d",&n);
	for(i=0;i<3*n;i++){
		scanf("%ld",&a[i]);
	}
	
//	printf("nは%dです\n", n);
//	printf("データの読み込み終了\n");
	//実際の処理
	lsum[0]=a[n];
	for(i=n+1;i<2*n;i++){
		lsum[i-n]=lsum[i-n-1]+a[i];
	}
	
	rsum[n-1]=a[2*n-1];
	for(i=2*n-2;i>=n;i--){
		rsum[i-n]=rsum[i-n+1]+a[i];
	}
	
	for(i=0;i<n;i++){
		push(a[i]);
	}
	
	
	for(i=n;i<2*n;i++){
		push(a[i]);
		if(i==n){
			ldec[i-n]=heap[0];
		}else{
			ldec[i-n]=ldec[i-n-1]+heap[0];
		}
		pop();
	}
	
	for(i=2*n;i<3*n;i++){
//		printf("a[i]=%d",a[i]);
		pushup(a[i]);
//		printf("heapup[%d]=%d\n",i-2*n,heapup[i-2*n]);
	}
	
	for(i=2*n-1;i>=n;i--){
//		for(j=0;j<=n;j++){
//			printf("heapup[%d]=%d\n",j,heapup[j]);
//		}
		pushup(a[i]);
//		printf("i=%d,a[i]=%d\n",i,a[i]);
		if(i==2*n-1){
			rdec[i-n]=heapup[0];
		}else{
			rdec[i-n]=rdec[i-n+1]+heapup[0];
		}
		
//		for(j=0;j<=n;j++){
//			printf("heapup[%d]=%d\n",j,heapup[j]);
//		}
		popup();
	}
	
//	for(i=0;i<n;i++){
//		printf("lsum[%d]=%d,ldec[%d]=%d,rsum[%d]=%d,rdec[%d]=%d\n",i,lsum[i],i,ldec[i],i,rsum[i],i,rdec[i]);
//	}
	
	for(i=0;i<=n;i++){
		if(i==0){
			ans=rdec[0]-rsum[0];
			temp=ans;
//			printf("i=%d,temp=%d\n",i,temp);
		}else if(i==n){
			temp=lsum[n-1]-ldec[n-1];
//			printf("i=%d,temp=%d\n",i,temp);
			if(temp>ans) ans=temp;
		}else{
			temp=lsum[i-1]-ldec[i-1]+rdec[i]-rsum[i];
//			printf("i=%d,temp=%d\n",i,temp);
			if(temp>ans) ans=temp;
		}
	}
	
//	printf("%ld\n",ans);
	
	for(i=0;i<n;i++){
		ans=ans+a[i];
	}
	for(i=2*n;i<3*n;i++){
		ans=ans-a[i];
	}
	
//	printf("計算部分終了\n");
	//出力
	
	printf("%lld\n",ans);
	
//	printf("結果の出力終了\n");
	
	return 0;
	
}