Official
B - 焼き肉の順番 / Order of the Grilled Meat Editorial by admin
swe-2-high解説
問題の要約
\(N\) 枚の肉があり、\(i\) 枚目は \(A_i\) 秒後に焼き上がる。最初に焼き上がる肉(=\(A_i\) が最小の肉)の番号を答える。最小値が複数ある場合は最も小さい番号を答える。
アルゴリズム
\(A_1, A_2, \ldots, A_N\) を順番に見ていき、「今までに見た中での最小値」と「その最小値を持つ肉の番号」を保持する。
\(i\) 枚目の肉を見たとき、\(A_i\) が現在の最小値より真に小さい場合のみ最小値と番号を更新する。\(A_i\) が現在の最小値と等しい場合は更新しない。これにより、最小値が複数ある場合には自然と最も小さい番号が残る(タイブレーク)。
擬似コード:
best ← 未定義
ans ← 未定義
for i = 1 to N:
if ans が未定義 or A_i < best:
best ← A_i
ans ← i
print ans
なお、入力を配列に保存する必要はなく、\(1\) 要素ずつ読みながら処理できる。
正しさの証明
主張: ループの \(i\) 回目の反復が終了した時点で、ans は \(A_1, \ldots, A_i\) の中で最小値を持つ添字のうち最小のものであり、best はその最小値である。
証明(帰納法):
- 基底(\(i = 1\)):
ansが未定義なので条件が満たされ、best ← A_1、ans ← 1が代入される。これは主張を満たす。 - 帰納ステップ: \(i - 1\) 回目終了時点で主張が成り立つと仮定する。\(i\) 回目の反復では:
- \(A_i < best\) の場合: \(A_1, \ldots, A_{i-1}\) の最小値は \(best\) であり、\(A_i\) はそれより小さいので、\(A_1, \ldots, A_i\) の最小値は \(A_i\) で、その値を持つ添字は \(i\) のみである。
best ← A_i、ans ← iと更新されるので主張を満たす。 - \(A_i \geq best\) の場合: \(A_1, \ldots, A_i\) の最小値は \(A_1, \ldots, A_{i-1}\) の最小値 \(best\) のままであり、最小値を持つ最小の添字も変わらない(\(A_i = best\) の場合でも \(i\) は既存の最小添字より大きいので、最小添字は変わらない)。更新しないので主張を満たす。
- \(A_i < best\) の場合: \(A_1, \ldots, A_{i-1}\) の最小値は \(best\) であり、\(A_i\) はそれより小さいので、\(A_1, \ldots, A_i\) の最小値は \(A_i\) で、その値を持つ添字は \(i\) のみである。
よって \(i = N\) 回終了時点で、ans は \(A_1, \ldots, A_N\) 全体で最小値を持つ最小の添字であり、これはまさに求める答えである。\(\blacksquare\)
計算量
- 時間計算量: \(O(N)\)(入力の読み込みを含む)。
- 空間計算量: C++ は \(O(1)\)、Python は \(O(N)\)。入力・出力として保持する配列や文字列も含む。
posted:
last update: