在庫の入庫と出庫と取り消しを処理する

  • 配列の処理
  • 問題 20
  • ふつう
  • 目安 31 分

入庫、出庫、取り消しの命令を順に処理して、最後の在庫を品名の順に出す。取り消しのたびにやり直さず、成功した命令の履歴を積んでおいて戻す練習です。

本番の試験は PC で受けることが多いので、PC での練習をすすめます。スマホでも、読んで、書いて、採点するところまで動きます。

入力は標準入力から読み、答えは標準出力に書きます。1 テストあたり 3 秒までです。

問題

倉庫の在庫を、N 個の命令を上から順に処理して管理します。はじめは、どの品の在庫も 0 個です。命令は次の 3 種類です。

  • 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
...
命令 N

1 行目に命令の数 N、続く N 行に、1 行に 1 つの命令が並びます。命令の中の語は半角の空白 1 つで区切られています。

出力の形式

在庫が 1 個以上ある品を、品名の辞書順 (英小文字の a から z の順に 1 文字目から比べ、短いほうが先に終わるならそちらが先) に、1 行に 1 品ずつ、品名と在庫の数を半角の空白 1 つで区切って書きます。在庫が 1 個以上ある品が 1 つも無ければ、EMPTY と 1 行だけ書きます。

制約

  • N は 1 以上 200000 以下の整数です
  • 品名 s は英小文字だけからなる、1 文字以上 10 文字以下の文字列です
  • 個数 x は 1 以上 1000000 以下の整数です

入力と出力の例

例 1

apple を 5 個、pen を 3 個入れたあと、apple を 2 個出して 3 個になります。pen を 10 個出そうとしますが、3 個しか無いので失敗します。次の取り消しは、失敗した出庫ではなく、その前の apple の出庫を取り消すので、apple は 5 個に戻ります。pen を 1 個出して 2 個になり、最後の取り消しでその出庫が戻って 3 個になります。

入力

7
IN apple 5
IN pen 3
OUT apple 2
OUT pen 10
UNDO
OUT pen 1
UNDO

出力

apple 5
pen 3

例 2

最初の取り消しは、取り消せる命令が無いので何も起きません。cup を 2 個入れて 2 個出すと在庫は 0 個になり、出力する品がありません。

入力

3
UNDO
IN cup 2
OUT cup 2

出力

EMPTY

ヒント

まだ開いていません

付箋は 3 枚。下の段ほど答えに近づきます

  1. ヒント 2

  2. ヒント 3答えに近い

main.py
import sys

lines = sys.stdin.read().split("\n")
n = int(lines[0])
commands = [lines[1 + i].split() for i in range(n)]

# ここから書く

入力

出力

「実行する」を押すと、ここに出力が出ます

できているか「提出して採点」を押すと、隠れたテストを全部走らせて、通ったかをここに出します