公式
A - 常連さんを見つけよう / Find the Regulars 解説 by admin
GPT 5.2 High概要
各利用者が「\(D\) 日のうち何日来館したか」を数え、来館日数が \(K\) 日以上の利用者番号を昇順に出力する問題です。
考察
重要なのは「来館回数」ではなく「来館した日数(=その日の記録に含まれているか)」を数えることです。
ただし本問題では「同じ日に同じ利用者が複数回記録されない」と保証されているため、各日のリストに現れた利用者を 1 回ずつ数え上げれば、そのまま“来館した日数”になります。
素朴に「各利用者 \(i\) について、全日程を見てその日に来ているかを探す(例えば線形探索)」のように書くと、実装が回りくどくなりがちです(入力のリストを何度も探すことになる)。
そこで、入力を読んだ順に「登場した利用者のカウントを 1 増やす」だけにすると、シンプルかつ確実に解けます。
例:
- \(D=3, K=2\)
- 1日目: {1,3}
- 2日目: {2,3}
- 3日目: {3}
→ 利用者3は3日来館、利用者1は1日、利用者2は1日
→ \(K=2\) 以上は「3」だけ
アルゴリズム
- 長さ \(N\) の配列
cntを用意し、cnt[i]を「利用者 \(i\) が来館した日数」とする(初期値 0)。 - 各日について入力を読み、来館者番号 \(s\) が現れるたびに
cnt[s] += 1とする。- 同じ日に同じ番号が重複しないため、これで「日数」を正しく数えられる。
- \(1 \le i \le N\) のうち
cnt[i] >= Kを満たすものを昇順に列挙して出力する。 - 条件を満たす利用者がいなければ
-1を出力する。
計算量
- 時間計算量: \(O\!\left(\sum_{j=1}^{D} M_j + N\right)\)
(入力に登場する人数の総和だけ加算し、最後に \(N\) 人をチェック) - 空間計算量: \(O(N)\)
(カウント配列cntのみ)
実装のポイント
M_j = 0の日があり得るので、「人数 \(M\) を読んだら、次に \(M\) 個だけ番号を読む」を徹底すると安全です。出力は昇順指定ですが、
i=1..Nの順に条件判定すれば自然に昇順になります。条件を満たす人が 0 人のときだけ
-1を出力する分岐を忘れないようにします。ソースコード
import sys
def main():
data = list(map(int, sys.stdin.buffer.read().split()))
if not data:
return
idx = 0
N = data[idx]; D = data[idx+1]; K = data[idx+2]
idx += 3
cnt = [0] * (N + 1)
for _ in range(D):
M = data[idx]
idx += 1
for _ in range(M):
s = data[idx]
idx += 1
cnt[s] += 1
ans = [str(i) for i in range(1, N + 1) if cnt[i] >= K]
if ans:
print(" ".join(ans))
else:
print("-1")
if __name__ == "__main__":
main()
この解説は gpt-5.2-high によって生成されました。
投稿日時:
最終更新: