Problem:
N: 通販 (Mail Order)

胡桃沢さんは、魔界通販で積み木のおもちゃを買った。

積み木は一辺の長さが1の立方体の形をしており、縦に $H$ 個、横に $W$ 個に分割されたマス目の上に積まれている。

真横から見ると、左から順に、$A_1, A_2, A_3, \dots, A_H$ 個のブロックが積まれて見えた。

正面から見ると、左から順に、$B_1, B_2, B_3, \dots, B_W$ 個のブロックが積まれて見えた。

胡桃沢さんは偉大なので、これらの情報だけからブロックの総数を当てようと考えた。

小さい数を答えて間違えると格好悪いので、考えられる最大の個数を答えたい。

入力

1 行目には整数 $H, W$ が空白区切りで与えられる。

2 行目には、真横から見たときの図を表す $H$ 個の整数 $A_1, A_2, A_3, \dots, A_H$ が空白区切りで与えられる。

3 行目には、正面から見たときの図を表す $W$ 個の整数 $B_1, B_2, B_3, \dots, B_W$ が空白区切りで与えられる。

出力

これらの情報から考えられるブロックの個数の最大値を出力しなさい。

制約

$H, W$ は $1$ 以上 $100 \ 000$ 以下の整数

$A_1, A_2, A_3, \dots, A_H$ は $1$ 以上 $100 \ 000 \ 000$ 以下の整数

$B_1, B_2, B_3, \dots, B_W$ は $1$ 以上 $100 \ 000 \ 000$ 以下の整数

すべての入力に対して、条件を満たすブロックの積み方があることが保証される

入力例1

2 2
1 5
1 5

出力例1

8

縦方向に $X$ 番目、横方向に $Y$ 番目のマスを $(X, Y)$ で表すことにします。

マス $(2, 2)$ に5個、マス $(1, 1)$、$(1, 2)$、$(2, 1)$ に $1$ 個ずつ積まれていると合計 $8$ 個のブロックが積まれることになります。

$9$ 個以上積まれている可能性は無いので、答えは $8$ です。

入力例2

3 3
2 4 5
3 1 5

出力例2

22

Solution in C (judge verdict: Accepted)

// AOJ 2928 Mail Order
// 2019.4.5 bal4u

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

//// 高速入力
#if 1
#define gc() getchar_unlocked()
#else
#define gc() getchar()
#endif
int in()
{
	int n = 0, c = gc();
	do n = 10 * n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

int H, W;
int _a[100005];
int _b[100005];
int *a, *b;
long long s[100005];

int upper_bound(int x)
{
	int m, l = 0, r = W;

	while (l < r) {
		m = (l + r) >> 1;
		if (b[m] == x) return m;
		if (b[m] < x) l = m + 1; else r = m;
	}
	return l - 1;
}

int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; }

int main()
{
	int i, k, t;
	long long ans;

	H = in(), W = in();
	for (i = 0; i < H; i++) _a[i] = in();
	for (i = 0; i < W; i++) _b[i] = in();
	if (H > W) t = H, H = W, W = t, a = _b, b = _a;  // 短い方を H, a[] にする
	else a = _a, b = _b;
	qsort(b, W, sizeof(int), cmp);
	for (i = 0; i < W; i++) s[i + 1] = s[i] + b[i];  // 累計和

	ans = 0; for (i = 0; i < H; i++) {
		k = upper_bound(a[i]);   // バイナリサーチでa[i]を超えない最大値のindexを得る
		ans += s[k + 1] + (long long)(W - k - 1)*a[i];
	}
	printf("%lld\n", ans);
	return 0;
}