A - 平坦な区間の判定 / Determining Flat Intervals Editorial by admin
Claude 4.6 Opus (Thinking)概要
長さ \(N\) の数列の中に、同じ値が \(K\) 個以上連続する箇所があるかどうかを判定する問題です。
考察
重要な気づき
まず素朴に考えると、すべての開始位置 \(l\) について区間 \([l, l+K-1]\) の要素が全部同じかを確認する方法があります。しかしこれは各区間で最大 \(K\) 回の比較が必要で、全体で \(O(NK)\) となり、\(N\) や \(K\) が大きい場合に非効率です。
ここで重要な気づきは、「同じ値が何個連続しているか」をカウントしながら1回走査すれば十分だということです。
具体例で理解する
例えば \(N = 7\), \(K = 3\), 高さが [3, 3, 5, 5, 5, 5, 2] の場合を考えます。
| 地点 \(i\) | \(H_i\) | 連続カウント |
|---|---|---|
| 1 | 3 | 1 |
| 2 | 3 | 2 |
| 3 | 5 | 1(リセット) |
| 4 | 5 | 2 |
| 5 | 5 | 3 ← \(K\) 以上! |
地点 5 の時点でカウントが \(3 \geq K\) になるので、平坦な区間が存在すると判定できます。
\(K = 1\) の特殊ケース
\(K = 1\) の場合、長さ1の区間はどの地点でも平坦なので、\(N \geq 1\) であれば必ず Yes です。
アルゴリズム
- \(K = 1\) なら即座に
Yesと答える。 - そうでなければ、変数
countを \(1\) に初期化し、地点 \(2\) から地点 \(N\) まで順に走査する。 - 地点 \(i\) の高さが地点 \(i-1\) と同じなら
countを \(1\) 増やす。異なればリセット(count = 1)。 countが \(K\) 以上になった時点で平坦な区間が見つかったのでYesを出力して終了。- 最後まで見つからなければ
Noを出力する。
この方法は「ランレングス」的な考え方で、同じ値の連続する長さ(ラン)を追跡しています。
計算量
- 時間計算量: \(O(N)\) — 配列を1回走査するだけ
- 空間計算量: \(O(N)\) — 入力の配列を保持するため(走査用の変数は \(O(1)\))
実装のポイント
countの初期値は \(1\): 地点1自体が長さ1の連続を形成しているため、\(0\) ではなく \(1\) から始めます。隣接比較でリセットを忘れない: \(H_i \neq H_{i-1}\) のときに
count = 1にリセットします。\(0\) にしてしまうと正しく動きません(現在の地点自体が新たな連続の始まりなので \(1\))。早期終了:
count >= Kになった瞬間にbreakすることで、無駄な走査を省けます。ただし最悪計算量は変わりません。ソースコード
N, K = map(int, input().split())
H = [int(input()) for _ in range(N)]
count = 1
found = False
if K == 1:
found = True
else:
for i in range(1, N):
if H[i] == H[i-1]:
count += 1
if count >= K:
found = True
break
else:
count = 1
print("Yes" if found else "No")
この解説は claude4.6opus-thinking によって生成されました。
posted:
last update: