B - 最初のアラート / First Alert 解説 by admin
Gemini 3.0 Flash概要
\(N\) 件のログを順番に確認し、重要度が初めて閾値 \(K\) 以上になった瞬間のログ番号(何番目か)を求める問題です。一度アラートを発報するとそれ以降は無視するため、条件を満たす「最小のインデックス」を探すことになります。
考察
この問題で重要な点は、「最初に条件を満たした時点で終了する」というルールです。
ログは \(P_1, P_2, \dots, P_N\) と順番に届きます。高橋君はこれらを先頭からチェックしていき、重要度が \(K\) 以上になった瞬間に対応を開始します。一度対応を始めると、その後のログがどれだけ重要であってもアラートは出しません。
したがって、以下の手順で解くことができます: 1. ログを \(i = 1\) から \(N\) まで順番に見ていく。 2. もし \(P_i \geq K\) ならば、その番号 \(i\) を出力してプログラムを終了する。 3. 全てのログを見ても条件を満たすものがなければ、\(-1\) を出力する。
制約を確認すると \(N \leq 2 \times 10^5\) であり、ログを一つずつ確認する「線形探索」を行っても十分に間に合います。
アルゴリズム
- 入力から \(N, K\) およびログの配列 \(P\) を受け取ります。
- 配列 \(P\) の要素を先頭から順にループで確認します。
- ループ内での現在の要素を \(P_i\) としたとき、
if P_i >= K:という条件分岐を行います。 - 条件を満たした場合は、現在の番号を出力して
exit()またはreturnで処理を打ち切ります。- プログラミング言語の配列は通常 0 番目から始まりますが、問題文では 1 番目から数える(1-indexed)ため、出力する際はインデックスに \(+1\) する必要があります。
- ループが最後まで終了した(=一度も条件を満たさなかった)場合は、\(-1\) を出力します。
計算量
- 時間計算量: \(O(N)\)
- ログの件数 \(N\) に対して、最大でも一度ずつ確認するため、ログの数に比例した時間で計算が終わります。
- 空間計算量: \(O(N)\)
- 全てのログの重要度を配列に格納して保持する場合、入力のサイズに比例したメモリを使用します。
実装のポイント
1-indexed への対応: 配列のインデックス(0, 1, 2, …)とログの番号(1, 2, 3, …)が 1 ズレていることに注意しましょう。
早期リターン: 条件を満たすものが見つかった瞬間に処理を終了させることで、余計な計算を省き、かつ「最初のアラート」だけを正確に捉えることができます。
高速な入出力: Python の場合、入力件数 \(N\) が \(2 \times 10^5\) 程度になると
input()を繰り返すよりもsys.stdin.read().split()などで一括で読み込む方が実行時間を短縮できる場合があります。ソースコード
import sys
def main():
# 標準入力からすべてのデータを読み込み、空白(スペース、改行など)で分割します
input_data = sys.stdin.read().split()
# 入力が空の場合は終了します
if not input_data:
return
# 1つ目の要素がN(ログの件数)、2つ目の要素がK(閾値)です
N = int(input_data[0])
K = int(input_data[1])
# 3つ目以降の要素が各ログの重要度 P_1, P_2, ..., P_N です
# 順番にチェックし、最初に閾値 K 以上になったログの番号を出力して終了します
for i in range(N):
# 重要度 P_i は input_data[i + 2] に格納されています
if int(input_data[i + 2]) >= K:
# ログの番号は 1-indexed なので i + 1 を出力します
print(i + 1)
return
# すべてのログを確認しても閾値以上の重要度が見つからなかった場合、-1 を出力します
print(-1)
if __name__ == "__main__":
main()
この解説は gemini-3-flash-preview によって生成されました。
投稿日時:
最終更新: