F - Double Sum Editorial by sounansya


簡単のため、0-indexedで考えます。

まず、目的の式を

0i<j<Nmax(AjAi,0)=0i<j<N{max(Aj,Ai)Ai}=0i<j<Nmax(Aj,Ai)0i<j<NAi\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の方)は全ての大きさ 22 のインデックスの集合 {i,j}\{i,j\} に対する max(Ai,Aj)\displaystyle \max\left(A_i,A_j\right) の総和と捉えられるので、この総和は AA の順番によらないことがわかります。これにより、 AA を昇順にソートしたものを BB とおくと、

=0i<j<Nmax(Aj,Ai)=0i<j<Nmax(Bj,Bi)=0i<j<NBj=j=0N1jBj \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}

として求めることができます。

一方、二項目(AiA_i の方)も同様に式変形をすると、

0i<j<NAi=i=0N1(N1i)Ai \sum_{0\le i < j< N} A_i=\sum_{i=0}^{N-1} (N-1-i)A_i

となるので、最終的に求める値は

i=0N1iBii=0N1(N1i)Ai\sum_{i=0}^{N-1} iB_i -\sum_{i=0}^{N-1} (N-1-i)A_i

と表すことができます。この値は配列のソートを用いることで簡単に求めることができます。

以上でこの問題が解けました。計算量はソートがボトルネックとなり O(NlogN)O(N\log N) となります。

実装例(Python3)

Copy
  1. N = int(input())
  2. A = list(map(int, input().split()))
  3. B = sorted(A)
  4. ans = 0
  5. for i in range(N):
  6. ans += i * B[i]
  7. ans -= (N - 1 - i) * A[i]
  8. print(ans)
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:



2025-04-20 (Sun)
23:38:03 +00:00