E - Bowls and Beans Editorial by tatyam


\(L_i := i - C_i\) と定義します.また,茶碗 \(0\) には豆が入っているものとします.

公式解説の考察より,以下の操作を繰り返せば良いです.

  • 最も後ろにある豆の入った茶碗を茶碗 \(i\) とする.茶碗 \(i\) に入った豆を以下の茶碗に移動させる.
    • 茶碗 \(L_i, L_i + 1, \dots, i-1\) の中に豆の入った茶碗があれば,そのうち最も後ろにあるものに豆を移動させる.
    • 茶碗 \(L_i, L_i + 1, \dots, i-1\) の中に豆の入った茶碗がなければ,そのうち \(L\) が最も小さい茶碗に豆を移動させる.

これを実装することで \(O(N)\) 時間で解くことができます.

実装例 (Python)

N = int(input())
C = [0] + list(map(int, input().split()))
A = [1] + list(map(int, input().split()))
L = [i - C[i] for i in range(N)]

ans = 0
for i in range(N - 1, 0, -1):
    # 最も後ろにある豆の入った茶碗を見つける
    if A[i] == 0:
        continue
    # この豆を以下の場所に移動させる
    ans += 1
    l = L[i]
    # 茶碗 [l:i] に豆の入った茶碗があれば,そのうち最も後ろの茶碗に移動
    if any(A[j] for j in range(i - 1, l - 1, -1)):
        continue
    # なければ,茶碗 argmin(L[l:i]) に移動
    mn = 1 << 60
    argmn = -1
    for j in range(i - 1, l - 1, -1):
        if mn > L[j]:
            mn = L[j]
            argmn = j
    A[argmn] = 1

print(ans)

posted:
last update: