在庫の 入庫と 出庫と 取り消しを処理する
- 配列の処理
- 問題 20
- ふつう
- 目安 31 分
入庫、
本番の
入力は
問題
倉庫の
IN s x品 s を x 個入庫します。品 s の 在庫が x 個増えます OUT s x品 s を x 個出庫します。品 s の 在庫が x 個以上 あれば、 在庫が x 個減ります。 在庫が x 個より 少なければ、 何も 起きません (この 出庫は 失敗です) UNDO取り消しです。成功した 入庫と 出庫の うち、 まだ 取り消していない もので 最も 新しい 1 つを 取り消します。 入庫を 取り消すと、 その品の 在庫が x 個減り、 出庫を 取り消すと、 その品の 在庫が x 個増えます。 取り消せる 命令が 1 つも 無ければ、 何も 起きません
失敗したUNDO) その
全部の
入力の形式
N
命令 1
命令 2
...
命令 N1 行目に
出力の形式
在庫が 1 個以上EMPTY と 1 行だけ
制約
- N は 1 以上 200000 以下の整数です
- 品名 s は
英小文字だけからなる、 1 文字以上 10 文字以下の 文字列です - 個数 x は 1 以上 1000000 以下の整数です
入力と出力の例
例 1
apple を
入力
7 IN apple 5 IN pen 3 OUT apple 2 OUT pen 10 UNDO OUT pen 1 UNDO
出力
apple 5 pen 3
例 2
最初の
入力
3 UNDO IN cup 2 OUT cup 2
出力
EMPTY
ヒント
まだ開いていません
付箋は 3 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3答えに近い
全部の
先に
解答
在庫を
Python
Python
import sys
lines = sys.stdin.read().split("\n")
n = int(lines[0])
stock = {}
history = []
for i in range(n):
parts = lines[1 + i].split()
if parts[0] == "UNDO":
if history:
name, change = history.pop()
stock[name] -= change
continue
name, count = parts[1], int(parts[2])
if parts[0] == "IN":
stock[name] = stock.get(name, 0) + count
history.append((name, count))
elif stock.get(name, 0) >= count:
stock[name] -= count
history.append((name, -count))
names = sorted(name for name, count in stock.items() if count > 0)
if names:
print("\n".join(f"{name} {stock[name]}" for name in names))
else:
print("EMPTY")JavaScript
JavaScript
const lines = require("fs").readFileSync(0, "utf8").split("\n");
const n = Number(lines[0]);
const stock = new Map();
const history = [];
for (let i = 0; i < n; i++) {
const parts = lines[1 + i].trim().split(" ");
if (parts[0] === "UNDO") {
if (history.length > 0) {
const [name, change] = history.pop();
stock.set(name, stock.get(name) - change);
}
continue;
}
const name = parts[1];
const count = Number(parts[2]);
const have = stock.get(name) ?? 0;
if (parts[0] === "IN") {
stock.set(name, have + count);
history.push([name, count]);
} else if (have >= count) {
stock.set(name, have - count);
history.push([name, -count]);
}
}
const names = [...stock.keys()].filter((name) => stock.get(name) > 0).sort();
console.log(names.length > 0 ? names.map((name) => `${name} ${stock.get(name)}`).join("\n") : "EMPTY");計算量
時間は O(N log N) です。
よく ある間違い
- 失敗した
出庫も 履歴に 積んでしまい、 次の 取り消しが 何も 戻さなくなる。 失敗した 出庫は 積みません - 履歴が
空の ときに 取り消しで 末尾を 取り出そうとして、 エラーで止まる - 在庫が 0 個に
なった 品まで name 0と出力してしまう。 出すのは 1 個以上の 品だけです - 出力する
品が 無い ときに 何も 書かない。 EMPTYと書く 決まりです - 品名を、
出てきた 順のまま 出力してしまう。 辞書順に 並べ替えます
解答を動かした版 Python 3.12.14Node.js 22.23.4確認日 2026/10/31