{ }codelper
队列P0351

先到先得的借伞处

学校门口有一个借伞处,一开始放着 u 把伞。
按发生的先后顺序给出 n 件事。
want 名字 表示叫这个名字的人来借伞。
借伞处有伞就立刻借走一把,没有就排到等待队伍的最后。
back 表示有一把借出去的伞还回来了。
如果有人在等,其中最先来的人立刻拿走这把伞并离开队伍。
如果没有人在等,就把伞放回借伞处。
每件事输出一行。
如果这件事让某人拿到了伞,输出那个人的名字;如果没有人拿到,输出 -。
最后一行输出还在等待的人数和借伞处里的伞数,用一个空格隔开。

输入
第一行给出 n 和 u,用一个空格隔开。
接下来 n 行,每行一件事。
1 ≤ n ≤ 9,000,0 ≤ u ≤ 9,000。
名字是 1 ~ 10 个英文小写字母,不同的人可能同名。
只有在至少有一把借出去的伞还没还回来时才会出现 back
输出
n + 1 行。
每件事输出拿到伞的人的名字或 -,最后一行输出等待的人数和借伞处的伞数
样例 1 · stdin
8 1
want mina
want joon
want sora
back
back
back
want hana
want dan
stdout
mina
-
-
joon
sora
-
hana
-
1 0
main.py
输入(stdin)

运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。

$ 就绪

请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。

其他语言怎么写?查看各语言题解 · 8 种语言题解

实现队列(先放进去的先出来)的工具因语言而异。
Python 用 collections.deque,append 放入,popleft() 取出。
Java 是 ArrayDeque 的 addLast、pollFirst,C# 是 Queue<T> 的 Enqueue、Dequeue,C++ 是 std::queue 的 push、front、pop。
C++ 的 pop() 不返回值,所以要先用 front() 读。
JS、TS、C 和 Craykon 没有单独的队列,就往数组(列表)末尾放(JS push,Craykon 添加),只把指向队首位置的数 head 一个一个往后移。
陷阱一:从末尾取(Python、JS 的 pop())就成了栈,最晚来的人反而先拿到。
示例的第一个 back 会输出 sora 而不是 joon。
陷阱二:取之前要先问队伍是不是空的。
从空队伍里取时发生什么,各语言不同。
Python 的 popleft() 以 IndexError 停下,C# 的 Dequeue() 以 InvalidOperationException 停下,Java 的 pollFirst() 给出 null,JS 的 shift() 不报错地给出 undefined。
所以在 JS 里示例的第三个 back 会输出 undefined,而且伞没有回到借伞处,hana 也借不到。
C++ 的 front() 在空队列上的行为没有定义,Craykon 读空列表的 0 号会报错停下。
陷阱三:还回来的伞要么给等待的人,要么放回借伞处,只能二选一。
如果先把借伞处的数量加一,又把伞给了等待的人,就多出一把伞,示例里的 dan 会拿到一把不存在的伞。

Pythonmain.py · 23 行
import sysfrom collections import deque lines = sys.stdin.read().split("\n")n, rack = map(int, lines[0].split())waiting = deque()          # 기다리는 사람들: 뒤로 넣고 앞에서 꺼낸다out = []for line in lines[1:n + 1]:    parts = line.split()    if parts[0] == "want":        if rack > 0:            rack -= 1            out.append(parts[1])        else:            waiting.append(parts[1])            out.append("-")    elif waiting:        out.append(waiting.popleft())   # 가장 먼저 온 사람이 받는다    else:        rack += 1                       # 기다리는 사람이 없으면 대여함에 꽂는다        out.append("-")out.append(f"{len(waiting)} {rack}")print("\n".join(out))
JavaScriptmain.js · 26 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const [n, u] = lines[0].trim().split(" ").map(Number);let rack = u;// JS에는 큐가 따로 없다. 배열 뒤에 넣고, 맨 앞 자리(head)만 뒤로 옮긴다.const waiting = [];let head = 0;const out = [];for (let i = 1; i <= n; i++) {  const [cmd, name] = lines[i].trim().split(" ");  if (cmd === "want") {    if (rack > 0) {      rack--;      out.push(name);    } else {      waiting.push(name);      out.push("-");    }  } else if (head < waiting.length) {    out.push(waiting[head++]); // 가장 먼저 온 사람이 받는다  } else {    rack++; // 기다리는 사람이 없으면 대여함에 꽂는다    out.push("-");  }}out.push(`${waiting.length - head} ${rack}`);console.log(out.join("\n"));
TypeScriptmain.ts · 28 行
import { readFileSync } from "node:fs"; const lines: string[] = readFileSync(0, "utf8").split("\n");const [n, u]: number[] = lines[0].trim().split(" ").map(Number);let rack: number = u;// TS에도 큐가 따로 없다. 배열 뒤에 넣고, 맨 앞 자리(head)만 뒤로 옮긴다.const waiting: string[] = [];let head = 0;const out: string[] = [];for (let i = 1; i <= n; i++) {  const [cmd, name]: string[] = lines[i].trim().split(" ");  if (cmd === "want") {    if (rack > 0) {      rack--;      out.push(name);    } else {      waiting.push(name);      out.push("-");    }  } else if (head < waiting.length) {    out.push(waiting[head++]); // 가장 먼저 온 사람이 받는다  } else {    rack++; // 기다리는 사람이 없으면 대여함에 꽂는다    out.push("-");  }}out.push(`${waiting.length - head} ${rack}`);console.log(out.join("\n"));
JavaMain.java · 34 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayDeque; public class Main {    public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        String[] first = in.readLine().trim().split(" ");        int n = Integer.parseInt(first[0]);        int rack = Integer.parseInt(first[1]);        ArrayDeque<String> waiting = new ArrayDeque<>();        StringBuilder out = new StringBuilder();        for (int i = 0; i < n; i++) {            String[] parts = in.readLine().trim().split(" ");            if (parts[0].equals("want")) {                if (rack > 0) {                    rack--;                    out.append(parts[1]).append('\n');                } else {                    waiting.addLast(parts[1]);                    out.append("-\n");                }            } else if (!waiting.isEmpty()) {                out.append(waiting.pollFirst()).append('\n'); // 가장 먼저 온 사람이 받는다            } else {                rack++; // 기다리는 사람이 없으면 대여함에 꽂는다                out.append("-\n");            }        }        out.append(waiting.size()).append(' ').append(rack);        System.out.println(out);    }}
C#Main.cs · 43 行
using System;using System.Collections.Generic;using System.Text; class Program{    static void Main()    {        string[] first = Console.ReadLine().Trim().Split(' ');        int n = int.Parse(first[0]);        int rack = int.Parse(first[1]);        var waiting = new Queue<string>();        var sb = new StringBuilder();        for (int i = 0; i < n; i++)        {            string[] parts = Console.ReadLine().Trim().Split(' ');            if (parts[0] == "want")            {                if (rack > 0)                {                    rack--;                    sb.Append(parts[1]).Append('\n');                }                else                {                    waiting.Enqueue(parts[1]);                    sb.Append("-\n");                }            }            else if (waiting.Count > 0)            {                sb.Append(waiting.Dequeue()).Append('\n'); // 가장 먼저 온 사람이 받는다            }            else            {                rack++; // 기다리는 사람이 없으면 대여함에 꽂는다                sb.Append("-\n");            }        }        sb.Append(waiting.Count).Append(' ').Append(rack).Append('\n');        Console.Write(sb);    }}
C++main.cpp · 35 行
#include <iostream>#include <queue>#include <string>using namespace std; int main() {    ios::sync_with_stdio(false);    cin.tie(nullptr);    int n, rack;    cin >> n >> rack;    queue<string> waiting;    for (int i = 0; i < n; i++) {        string cmd;        cin >> cmd;        if (cmd == "want") {            string name;            cin >> name;            if (rack > 0) {                rack--;                cout << name << '\n';            } else {                waiting.push(name);                cout << "-\n";            }        } else if (!waiting.empty()) {            cout << waiting.front() << '\n'; // 가장 먼저 온 사람이 받는다            waiting.pop();                   // pop()은 값을 돌려주지 않는다        } else {            rack++; // 기다리는 사람이 없으면 대여함에 꽂는다            cout << "-\n";        }    }    cout << waiting.size() << ' ' << rack << '\n';    return 0;}
Cmain.c · 35 行
#include <stdio.h>#include <string.h> #define MAXN 9000 /* 배열로 만든 큐: tail 자리에 넣고 head 자리에서 꺼낸다.   기다리는 사람은 모두 합쳐 n명을 넘지 않으니 MAXN칸이면 된다. */static char waiting[MAXN][11]; int main(void) {    int n, rack;    scanf("%d %d", &n, &rack);    int head = 0, tail = 0;    for (int i = 0; i < n; i++) {        char cmd[8], name[11];        scanf("%7s", cmd);        if (strcmp(cmd, "want") == 0) {            scanf("%10s", name);            if (rack > 0) {                rack--;                printf("%s\n", name);            } else {                strcpy(waiting[tail++], name);                printf("-\n");            }        } else if (head < tail) {            printf("%s\n", waiting[head++]); /* 가장 먼저 온 사람이 받는다 */        } else {            rack++; /* 기다리는 사람이 없으면 대여함에 꽂는다 */            printf("-\n");        }    }    printf("%d %d\n", tail - head, rack);    return 0;}
Craykonmain.cray · 36 行
첫줄 = 控制台.读数字();n = 첫줄[0];rack = 첫줄[1];// 목록으로 만든 큐: 뒤에 넣고, 맨 앞 자리(head)만 뒤로 옮긴다waiting = [];head = 0;循环 (i = 0; i < n; i++){    parts = 控制台.读行().去空白().分割();    如果 (parts[0] == "want")    {        如果 (rack > 0)        {            rack -= 1;            控制台.输出(parts[1]);        }        否则        {            waiting.添加(parts[1]);            控制台.输出("-");        }    }    否则 如果 (head < waiting.数量)    {        // 가장 먼저 온 사람이 받는다        控制台.输出(waiting[head]);        head += 1;    }    否则    {        // 기다리는 사람이 없으면 대여함에 꽂는다        rack += 1;        控制台.输出("-");    }}控制台.输出(waiting.数量 - head + " " + rack);