A - 図書館の貸出管理 / Library Loan Management 解説 by admin 印刷ページ
GPT 5.2 High概要
各図書館・各ジャンルの在庫数を配列で管理し、貸出申請を時系列に1件ずつ処理して在庫を減らす(0なら失敗回数を増やす)問題です。
考察
重要なのは、各申請が参照するのは「特定の図書館 \(v_k\) の特定ジャンル \(d_k\)」の在庫だけであり、他のジャンルや他の図書館の情報は不要という点です。
つまり、毎回やるべきことは次の2択だけです。
- その在庫が \(>0\) なら \(-1\)
- \(=0\) なら失敗回数 \(+1\)
ここで素朴にやりがちな失敗として、例えば以下のようなことがあります。
- 申請のたびに図書館の情報を入力から探し直す / 辞書検索を多用する
- 文字列として読み込んで毎回パースする
- 出力のたびに都度
printを大量に呼ぶ
本問題は最大で \(\sum M_i \le 10^5\)、申請数が \(Q \le 2\times 10^5\) と大きいため、「1申請あたり \(O(1)\) で更新できる形」で持ち、入出力も高速にする必要があります。
そのために、各図書館の在庫を 二重配列(リストのリスト) でそのまま保持し、申請 \((v,d)\) が来たら libs[v][d] を直接更新します。これなら1件あたり定数時間で処理できます。
例:図書館2のジャンル3の在庫が 0 のときに借りようとしても減らせず、失敗回数だけ増えます。
アルゴリズム
- 入力から \(N\) を読む。
- 各図書館 \(i\) について、ジャンル数 \(M_i\) と初期在庫 \(S_{i,1..M_i}\) を読み、
libs[i] = [S_{i,1}, ..., S_{i,M_i}]として保存する。 - \(Q\) 件の申請を順に処理する:
v, dを 0-index に直す(v-1,d-1)libs[v][d] > 0ならlibs[v][d] -= 1- そうでなければ
fail += 1
- 最後に各図書館の配列をスペース区切りで出力し、最終行に
failを出力する。
計算量
- 時間計算量: \(O\!\left(\sum_{i=1}^{N} M_i + Q\right)\)
(初期在庫の読み込み + 申請を1回ずつ処理) - 空間計算量: \(O\!\left(\sum_{i=1}^{N} M_i\right)\)
(全ジャンルの在庫数を保持)
実装のポイント
0-index に変換:入力は 1-index なので、
v-1,d-1にして配列アクセスを簡単にします。高速入力:
sys.stdin.buffer.read().split()でまとめて読み、iterで順に取り出すと Python でも十分高速です。高速出力:
printを大量に呼ぶ代わりに、文字列を配列outに貯めて最後に"\n".join(out)でまとめて出力します。ソースコード
import sys
def main():
it = iter(map(int, sys.stdin.buffer.read().split()))
N = next(it)
libs = []
for _ in range(N):
Mi = next(it)
libs.append([next(it) for _ in range(Mi)])
Q = next(it)
fail = 0
for _ in range(Q):
v = next(it) - 1
d = next(it) - 1
a = libs[v]
if a[d] > 0:
a[d] -= 1
else:
fail += 1
out = []
for a in libs:
out.append(" ".join(map(str, a)))
out.append(str(fail))
sys.stdout.write("\n".join(out))
if __name__ == "__main__":
main()
この解説は gpt-5.2-high によって生成されました。
投稿日時:
最終更新: