Problem:
Score : 300 points

Problem Statement

The season for Snuke Festival has come again this year. First of all, Ringo will perform a ritual to summon Snuke. For the ritual, he needs an altar, which consists of three parts, one in each of the three categories: upper, middle and lower.

He has N parts for each of the three categories. The size of the i-th upper part is A_i, the size of the i-th middle part is B_i, and the size of the i-th lower part is C_i.

To build an altar, the size of the middle part must be strictly greater than that of the upper part, and the size of the lower part must be strictly greater than that of the middle part. On the other hand, any three parts that satisfy these conditions can be combined to form an altar.

How many different altars can Ringo build? Here, two altars are considered different when at least one of the three parts used is different.

Constraints

1 \leq N \leq 10^5

1 \leq A_i \leq 10^9(1\leq i\leq N)

1 \leq B_i \leq 10^9(1\leq i\leq N)

1 \leq C_i \leq 10^9(1\leq i\leq N)

All input values are integers.

Input

Input is given from Standard Input in the following format:

N
A_1 ... A_N
B_1 ... B_N
C_1 ... C_N

Output

Print the number of different altars that Ringo can build.

Sample Input 1

2
1 5
2 4
3 6

Sample Output 1

3

The following three altars can be built:

Upper: 1-st part, Middle: 1-st part, Lower: 1-st part

Upper: 1-st part, Middle: 1-st part, Lower: 2-nd part

Upper: 1-st part, Middle: 2-nd part, Lower: 2-nd part

Sample Input 2

3
1 1 1
2 2 2
3 3 3

Sample Output 2

27

Sample Input 3

6
3 14 159 2 6 53
58 9 79 323 84 6
2643 383 2 79 50 288

Sample Output 3

87

Solution in C (GCC 5.4.1) (judge verdict: Runtime Error)



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


//#define DEBUG1
//#define DEBUG2
//#define DEBUGF

int A[100000];
int B[100000];
int C[100000];
int a[10000];
int c[10000];

int n;
int al, ar, cl, cr;
int tmp = 0;

int cmp(const void *p, const void *q) {
	return *(int*)p - *(int*)q;
}

int main() {
	int Less_than(int n, int array[], int left, int right, int value);


	//入力作業
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		scanf("%d", &A[i]);
	}
	for (int i = 0; i < n; i++) {
		scanf("%d", &B[i]);
	}
	for (int i = 0; i < n; i++) {
		scanf("%d", &C[i]);
	}

	//入力値の表示
#ifdef DEBUG1
	for (int i = 0; i < n; i++) {
		printf("A[%d] = %d\n", i, A[i]);
	}
	for (int i = 0; i < n; i++) {
		printf("B[%d] = %d\n", i, B[i]);
	}
	for (int i = 0; i < n; i++) {
		printf("C[%d] = %d\n", i, C[i]);
	}
	printf("\n");
#endif

	//ソート作業
	qsort((void *)A, n, sizeof(int), cmp);
	qsort((void *)B, n, sizeof(int), cmp);
	qsort((void *)C, n, sizeof(int), cmp);

	//ソート結果の表示
#ifdef DEBUG2
	for (int i = 0; i < n; i++) {
		printf("A[%d] = %d\n", i, A[i]);
	}
	for (int i = 0; i < n; i++) {
		printf("B[%d] = %d\n", i, B[i]);
	}
	for (int i = 0; i < n; i++) {
		printf("C[%d] = %d\n", i, C[i]);
	}
#endif

	//演算作業
	//その１　各要素数のカウントデータ収集作業

	//A[n]のカウントデータ収集作業
	al = 0;
	ar = n - 1;
	cl = 0;
	cr = n - 1;

	for (int i = 0; i < n; i++) {
#ifdef DEBUG1
		a[i] = bin_search(A, al, ar, B[i]);
		printf("bin_search(A[], %d, %d, %d) = %d\n", al, ar, B[i], a[i]);
#endif

		a[i] = Less_than(n, A, al, ar, B[i]);
		c[i] = Less_more(n, C, cl, cr, B[i]);

		tmp = tmp + a[i] * c[i];

#ifdef DEBUG2
		printf("Less_than(%d, A[], %d, %d, %d) = %d\n", n, al, ar, B[i], a[i]);
		printf("Less_more(%d, C[], %d, %d, %d) = %d\n", n, cl, cr, B[i], c[i]);
		printf("i = %d tmp = %d\n", i, tmp);
#endif
	}
	printf("%d\n", tmp);

#ifdef DEBUG2
	//getch();
#endif
}

/*
関数	：int Less_more(int n, int array[], int left, int right, int value)
概要	：超えるの要素数を取得する
入力値：要素数 : n, 配列 : array[], 開始イテレータ : left, 終了イテレータ : right, 探索データ : x
戻り値：超えるの要素数
要件	：配列 : a[]は未ソートで可
：left、right は前方向イテレータの要件を満たす事
*/
int Less_more(int n, int array[], int left, int right, int value) {

	int bin_search(int array[], int left, int right, int value);

	//変数を定義する
	int i;
	int result = -1;
	int s;

	//初期値を入力する
	int lt = -1;
	int flag_err = 0;

	//探索対象データの入力
	int first = left;//開始イテレータの入力:first
	int last = right;//終了イテレータの入力:last

					 //配列のソート：qsort() ＊＊＊＊＊省略＊＊＊＊＊

					 //探索条件データの入力
	s = first;//開始イテレータの入力:first


	if ((first > last) || (first > n - 1) || (last > n - 1)) {//エラーチェック:first > last || first > n-1 || last > n-1
		printf("%s\n", "探索範囲エラーです");
		flag_err = 1;//エラーフラグTrue

					 //エラー処理は後程記述とする
	}
	//if (value > array[last]) {//エラーチェック:value > array[last]
	//	printf("%s\n", "このデータ内にはありません");
	//	flag_err = 1;//エラーフラグTrue

	//				 //エラー処理は後程記述とする
	//}
	//エラーでは無い場合
	if (flag_err != 1) {

		//探索する
		int r = bin_search(array, s, last, value);//bin_sartch()を実行する
#ifdef DEBUGF
		printf("r = %d\n", r);
#endif
		if (r < 0) {//if (bin_sartch() < 0)  一致無しか？

			i = r * -1;

			if (array[i] <= value) {
				if (i == s) {
					lt = -1;//一つ右は存在しない。対象配列内に該当なしエラーなので - 1
				}
				else
				{
					lt = last + 1 + r;//ひとつ右のイテレータ存在するのでそれを返す
				}
			}
			else
			{
				lt = last + 1 + r;//イテレータを要素数に変換する
			}
		}
		else//一致有り
		{
			lt = last + 1 - r;//イテレータを要素数に変換する
		}

		//結果を返す
		result = lt;
#ifdef DEBUGF
		printf("超える数 result = %d\n", result);
#endif
	}
	else
	{
		//エラーの場合
		printf("%s\n", "エラーです");
	}
#ifdef DEBUGF
	getch();
#endif
	return result;
}

/*
関数	：int Less_than(int n, int array[], int left, int right, int value)
概要	：未満の要素数を取得する
入力値：要素数 : n, 配列 : array[], 開始イテレータ : left, 終了イテレータ : right, 探索データ : x
戻り値：未満の要素数
要件	：配列 : a[]は未ソートで可
：left、right は前方向イテレータの要件を満たす事
*/
int Less_than(int n, int array[], int left, int right, int value) {

	int bin_search(int array[], int left, int right, int value);

	//変数を定義する
	int i;
	int result = -1;
	int s;

	//初期値を入力する
	int lt = -1;
	int flag_err = 0;

	//探索対象データの入力
	int first = left;//開始イテレータの入力:first
	int last = right;//終了イテレータの入力:last

					 //配列のソート：qsort() ＊＊＊＊＊省略＊＊＊＊＊

					 //探索条件データの入力
	s = first;//開始イテレータの入力:first


	if ((first > last) || (first > n - 1) || (last > n - 1)) {//エラーチェック:first > last || first > n-1 || last > n-1
		printf("%s\n", "探索範囲エラーです");
		flag_err = 1;//エラーフラグTrue

					 //エラー処理は後程記述とする
	}
	if (value < array[first]) {//エラーチェック:value < array[first]
		printf("%s\n", "このデータ内にはありません");
		flag_err = 1;//エラーフラグTrue

					 //エラー処理は後程記述とする
	}
	//エラーでは無い場合
	if (flag_err != 1) {

		//探索する
		int r = bin_search(array, s, last, value);//bin_sartch()を実行する
#ifdef DEBUGF
		printf("r = %d\n", r);
#endif
		if (r < 0) {//if (bin_sartch() < 0)  一致無しか？

			i = r * -1;

			if (array[i] >= value) {
				if (i == s) {
					lt = -1;//一つ左は存在しない。対象配列内に該当なしエラーなので - 1
				}
				else
				{
					lt = i + 1 - 1 - s;//ひとつ左のイテレータ存在するのでそれを返す
				}
			}
			else
			{
				lt = i - s;//イテレータを要素数に変換する
			}
		}
		else//一致有り
		{
			lt = r - 1 - s;//イテレータを要素数に変換する
		}

		//結果を返す
		result = lt;
#ifdef DEBUGF
		printf("未満数 result = %d\n", result);
#endif
	}
	else
	{
		//エラーの場合
		printf("%s\n", "エラーです");
	}
#ifdef DEBUGF
	getch();
#endif
	return result;
}

/*
関数	：int bin_search(int array[], int left, int right, int value)
概要	：二分探索を実行する
入力値：配列 : array[], 開始イテレータ : left, 終了イテレータ : right, 探索データ : value
戻り値：一致ありの場合：一致要素のイテレータプラス１を返す
：一致無しの場合：最後に探索したイテレータプラス１のマイナス値を返す
要件	：配列 : array[]は昇順にソート済である事
：left、right は前方向イテレータの要件を満たす事
*/
int bin_search(int array[], int left, int right, int value) {

	int result = -1;
	int mid;

#ifdef DEBUG1
	printf("value = %d\n", value);
#endif
	//while (left <= right) {
	while (left <= right) {

		mid = (left + right) / 2;
#ifdef DEBUG1
		printf("left = %d\t mid = %d\t right = %d\n", left, mid, right);
#endif
		if (array[mid] == value) {
#ifdef DEBUG1
			printf("array[%d]=%d == %d\n", mid, array[mid], value);
#endif
			result = mid + 1;

			left = right + 1;
		}
		if (array[mid] > value) {
#ifdef DEBUG1
			printf("array[%d]=%d > %d\n", mid, array[mid], value);
#endif
			right = mid - 1;

			result = mid * -1;
		}
		if (array[mid] < value) {
#ifdef DEBUG1
			printf("array[%d]=%d < %d\n", mid, array[mid], value);
#endif
			left = mid + 1;

			result = (mid + 1) * -1;
		}
	}

#ifdef DEBUG1
	if (result > 0) {
		printf("%s", "二分探索 一致あり ");
	}
	else
	{
		printf("%s", "二分探索 一致無し　 ");
	}
	printf("result = %d\n", result);
	getch();
#endif
	return result;
}