B - ドミノ倒しの一撃 / A Single Strike of Dominoes Editorial by admin
GPT 5.4 High概要
この問題の本質は、連鎖が起きても各柱が追加で受けるダメージは高々 \(1\) だけ、という点です。
したがって、1本目は \(X\) だけで倒す必要があり、2本目以降は「左隣が倒れる」と仮定すれば \(X+1\) で倒せればよいので、答えは
\[ \max \left( A_1,\ \max_{2 \le i \le N}(A_i-1) \right) \]
となります。
考察
まず、各柱がどうやって倒れるかを整理します。
- すべての柱は最初に同時に \(X\) のダメージを受ける
- その後、左から順に見ていき、
- もし左隣の柱が倒れていれば、その柱はさらに \(1\) ダメージを受ける
ここで大事なのは、
- 1本目 は左隣が存在しないので、受けるダメージは \(X\) だけ
- 2本目以降 は、左隣が倒れていれば受けるダメージは \(X+1\)
ということです。
重要な気づき
連鎖と聞くと「右に行くほどどんどん大きなダメージが伝わる」と思いがちですが、そうではありません。
各柱が追加で受けるのは 左隣からの \(1\) だけ です。
つまり、各柱の判定は次のようになります。
- 1本目が倒れる条件:\(A_1 \le X\)
- 2本目が倒れる条件:1本目が倒れていて、かつ \(A_2 \le X+1\)
- 3本目が倒れる条件:2本目が倒れていて、かつ \(A_3 \le X+1\)
- …
この形を見ると、最初の1本目さえ倒れれば、以降は全部「\(X+1\) で倒せるかどうか」だけ で決まります。
必要条件
すべて倒すには、当然
- 1本目について \(X \ge A_1\)
- 2本目以降について \(X+1 \ge A_i\)
すなわち \(X \ge A_i-1\)
が必要です。
したがって、\(X\) は少なくとも
\[ \max \left( A_1,\ \max_{2 \le i \le N}(A_i-1) \right) \]
以上でなければなりません。
これで本当に十分か?
はい、十分です。
実際にこの値を \(X\) とすると、
- 1本目は \(A_1 \le X\) なので倒れる
- 1本目が倒れたので、2本目は \(X+1\) のダメージを受ける
- しかも \(A_2 \le X+1\) なので倒れる
- すると3本目も同様に倒れる
- …
- これを順に繰り返せば、すべての柱が倒れる
と分かります。
つまり、この値は「必要」でもあり「十分」でもあるので、そのまま最小値です。
具体例
例えば
\[ A = [5, 7, 6, 4] \]
のとき、
- 1本目のために \(X \ge 5\)
- 2本目以降のために
- \(X \ge 7-1=6\)
- \(X \ge 6-1=5\)
- \(X \ge 4-1=3\)
なので答えは
\[ \max(5,6,5,3)=6 \]
です。
実際、\(X=6\) なら
- 1本目:\(6\) 受けて倒れる
- 2本目:\(6+1=7\) 受けて倒れる
- 3本目:\(7\) 受けて倒れる
- 4本目:\(7\) 受けて倒れる
となり、全部倒れます。
素朴な方法がなぜ不要か
素朴には、
- ある \(X\) を決めてシミュレーションする
- それをいろいろな \(X\) で試す
という方法が考えられます。
しかし \(A_i\) は最大 \(10^9\) なので、\(X\) を小さい方から順に試すのは到底間に合いません。
この問題は連鎖の仕組みを正しく読むと、実はシミュレーションすらほぼ不要で、
各柱に必要な条件を式にするだけで答えが一発で分かる のがポイントです。
アルゴリズム
以下を計算します。
- 答えを最初は \(A_1\) にする
(1本目は \(X\) だけで倒さなければならないため) - 2本目以降について、\(A_i-1\) を見て答えを更新する
- 最後にその最大値を出力する
式で書くと、
\[ \text{ans} = \max \left( A_1,\ A_2-1,\ A_3-1,\ \dots,\ A_N-1 \right) \]
です。
計算量
- 時間計算量: \(O(N)\)
- 空間計算量: \(O(1)\)
実装のポイント
- 1本目だけ条件が異なり、必要なのは \(A_1\) そのものです
- 2本目以降は「左隣が倒れるなら \(+1\) ダメージ」が入るので、必要条件は \(A_i-1\)
- Python では 0-indexed 配列なので、コードでは
A[0]が1本目A[i] - 1をi=1から見ていけばよいです
この方針をそのまま実装したのが提出コードです。
ソースコード
import sys
def main():
input = sys.stdin.readline
N = int(input())
A = list(map(int, input().split()))
ans = A[0]
for i in range(1, N):
ans = max(ans, A[i] - 1)
print(ans)
if __name__ == "__main__":
main()
この解説は gpt-5.4-high によって生成されました。
posted:
last update: