Please sign in first.
D - Swap to Gather 解説
by
sounansya
\(S\) の中の 1
の個数を \(M\) とします。また、左から \(i\) 番目の 1
の場所を \(A_i\) とします。(この \(i\) は 0-indexed とします)
\(S\) の中の左から \(k\) 文字目から \(k+M-1\) 文字目までに 1
を集めることを考えます。すると、1
同士の相対的な位置関係は変わらないことから、左から \(i\) 番目の 1
は左から \(A_i\) 番目の場所から左から \(k+i\) 番目に移動させれば良いので、全体的な移動回数は
\(\displaystyle \sum_{i=0}^{M-1}|A_i-(k+i)|=\sum_{i=0}^{M-1}|k-(A_i-i)|\) となります。
ここで、一般に \(\displaystyle f(x)=\sum_{i=0}^{N-1} |x-X_i|\) の値は \(x\) を \(X\) の中央値とすると最小になることが知られています。
\(A\) は狭義単調増加数列であるので、 \(B_i=A_i-i\) は広義単調増加数列となります。よって、 \(B\) の中央値は \(B_{\lfloor M/2\rfloor }\) となるので、 \(k=B_{\lfloor M/2\rfloor }\) とすると操作回数の最小値が得られます。
以上を適切に実装することでこの問題に正答することができます。
n = int(input())
s = input()
a = []
for i in range(n):
if s[i] == "1":
a.append(i - len(a))
ki = a[len(a) >> 1]
ans = 0
for i in a:
ans += abs(i - ki)
print(ans)
投稿日時:
最終更新: