yamake's blog

主に競プロ、たまに自転車

Codeforces Round #629 F - Make k Equal

 これを自力ACしました。バチャ中はEに引っかかってここまでたどり着けなかったけど、先にFを見ておくべきでした...。

問題概要

 数列 a が与えられる。以下の操作を繰り返して a 内に少なくとも k 個の等しい要素を取得しなさい。

  1. a 内の最大の要素の大きさを 1 小さくする。
  2. a 内の最小の要素の大きさを 1 大きくする。

解説

 まず a をソートする。k 個出現させる要素の大きさは最初 a に入っている要素の大きさと必ず一致するので、何を k 個得るかを全探索する。
  a[i]k 個得るときにかかるコストは 1. a[i] 以下を全てインクリメント、2. a[i] 以上を全てデクリメント、3. 両方するの 3 通りが考えられる。それぞれのコストは

  1. ia[i]-\Sigma_{j=0}^{i-1}{a[j]}+(k-i-1),
  2. (n-i)a[i]-\Sigma_{j=i+1}^{n-1}{a[j]}+(k-(n-i)),
  3. ia[i]-\Sigma_{j=0}^{i-1}{a[j]}+(n-i)a[i]-\Sigma_{j=i+1}^{n-1}{a[j]}+(k-n)

 によって求められ、答えはこれらの最小値である。
 総和の部分はあらかじめ累積和を求めておくと O(1) で求められるため、時間計算量はソートにより O(N \log(N)) となる。

提出コード