F - Double Sum Editorial by sounansya
簡単のため、0-indexedで考えます。
まず、目的の式を
\[\displaystyle \sum_{0\le i < j< N}\max(A_j-A_i,0) = \sum_{0\le i < j< N}\left\{ \max\left(A_j,A_i \right)-A_i\right\} = \sum_{0\le i < j< N}\max\left(A_j,A_i \right)-\sum_{0\le i < j< N}A_i\]
と式変形します。
ここで、一項目(maxの方)は全ての大きさ \(2\) のインデックスの集合 \(\{i,j\}\) に対する \(\displaystyle \max\left(A_i,A_j\right)\) の総和と捉えられるので、この総和は \(A\) の順番によらないことがわかります。これにより、 \(A\) を昇順にソートしたものを \(B\) とおくと、
\[ \begin{aligned} &\phantom{=} \sum_{0\le i < j< N} \max\left(A_j,A_i \right)\\ &= \sum_{0\le i < j< N} \max\left(B_j,B_i \right)\\ &=\sum_{0\le i < j< N} B_j\\ &=\sum_{j=0}^{N-1} jB_j \end{aligned} \]
として求めることができます。
一方、二項目(\(A_i\) の方)も同様に式変形をすると、
\[ \sum_{0\le i < j< N} A_i=\sum_{i=0}^{N-1} (N-1-i)A_i \]
となるので、最終的に求める値は
\[\sum_{i=0}^{N-1} iB_i -\sum_{i=0}^{N-1} (N-1-i)A_i\]
と表すことができます。この値は配列のソートを用いることで簡単に求めることができます。
以上でこの問題が解けました。計算量はソートがボトルネックとなり \(O(N\log N)\) となります。
N = int(input())
A = list(map(int, input().split()))
B = sorted(A)
ans = 0
for i in range(N):
ans += i * B[i]
ans -= (N - 1 - i) * A[i]
print(ans)
posted:
last update: