3 13
num add 5
word add kiwi
num add 0012
num add 300
num add 5
num add 7
word add fig
word add kiwi
num del 300
num show
word show
word del plum
word show
stdout
7 5
kiwi fig
kiwi fig
main.py
错误列表00F8 ↓ · ⇧F8 ↑
输入(stdin)
运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。
$ 就绪
请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。
其他语言怎么写?查看各语言题解 · 4 种语言题解
本题只接受有泛型的 TypeScript、Java、C# 和 C++(C++ 用类模板)。 Python、JavaScript 不写类型,一个类本来就能装任何东西(Python 的 TypeVar 只是写着,运行时不检查),C 和 Craykon 没有类型参数。 四种语言"找相同项目"的方式不同。 TS 的 indexOf 用 === 查找,所以数和字符串按值比较。 Java 不能写 Recent<int>,要用 Recent<Integer> 存放,T 之间用 equals 比较。 C# 对没有约束的 T 用 == 会编译错误,所以用 EqualityComparer<T>.Default.Equals;Recent<int> 存 int 不用装箱。 C++ 模板为每个 T 单独生成代码,std::find 调用那个 T 的 ==。 三个陷阱:① 在 Java 泛型代码中,items.get(i) == x 问的是是否同一个对象。 Integer 只对 -128~127 共用预先建好的对象,所以小数看起来没问题,但 1000 或读进来的单词即使值相同也是不同对象,不会被移除,会进去两次。 ② 在 TS、C++ 中把整数按读到的字符串原样放进 Recent<string>,007 和 7 就成了不同的项目,输出也是 007。 要用 Number(x)、std::stoll 转换后放进 Recent<number>、Recent<long long>。 ③ 在 C# 中为了能用 == 而加上 where T : class 约束,可以编译通过,但泛型里的 == 是引用比较,不是 string 的值比较,读进来的相同单词会被当成不同(而且也装不了 int)。
TypeScriptmain.ts · 39 行
import { readFileSync } from "node:fs";// 가장 최근 것부터 k개까지만 기억하는 목록. T가 무엇이든 같은 코드로 쓴다class Recent<T> { private items: T[] = []; constructor(private readonly capacity: number) {} add(x: T): void { this.remove(x); // 이미 있으면 빼고 this.items.unshift(x); // 맨 앞(가장 최근)에 넣고 if (this.items.length > this.capacity) this.items.pop(); // 넘치면 가장 오래된 것을 버린다 } remove(x: T): void { const i = this.items.indexOf(x); // indexOf는 ===로 찾는다: 수와 문자열은 값으로 같다 if (i >= 0) this.items.splice(i, 1); } show(): string { return this.items.length === 0 ? "-" : this.items.join(" "); }}const lines = readFileSync(0, "utf8").split("\n");const [k, q] = lines[0].split(" ").map(Number);const nums = new Recent<number>(k); // 수는 수로 바꿔 담아야 "007"과 "7"이 같아진다const words = new Recent<string>(k);const out: string[] = [];for (const line of lines.slice(1, 1 + q)) { const [kind, cmd, arg] = line.trim().split(" "); if (kind === "num") { if (cmd === "show") out.push(nums.show()); else if (cmd === "add") nums.add(Number(arg)); else nums.remove(Number(arg)); } else { if (cmd === "show") out.push(words.show()); else if (cmd === "add") words.add(arg); else words.remove(arg); }}console.log(out.join("\n"));
JavaMain.java · 63 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List;// 가장 최근 것부터 capacity개까지만 기억하는 목록. T가 무엇이든 같은 코드로 쓴다class Recent<T> { private final List<T> items = new ArrayList<>(); private final int capacity; Recent(int capacity) { this.capacity = capacity; } void add(T x) { remove(x); items.add(0, x); if (items.size() > capacity) items.remove(items.size() - 1); } void remove(T x) { // T는 객체라서 ==는 같은 객체인지를 묻는다. 값이 같은지는 equals로 묻는다 for (int i = 0; i < items.size(); i++) { if (items.get(i).equals(x)) { items.remove(i); return; } } } String show() { if (items.isEmpty()) return "-"; StringBuilder sb = new StringBuilder(); for (T x : items) { if (sb.length() > 0) sb.append(' '); sb.append(x); } return sb.toString(); }}public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] first = br.readLine().trim().split(" "); int k = Integer.parseInt(first[0]), q = Integer.parseInt(first[1]); Recent<Integer> nums = new Recent<>(k); // Recent<int>는 안 된다: 제네릭에는 Integer로 담는다 Recent<String> words = new Recent<>(k); StringBuilder out = new StringBuilder(); for (int e = 0; e < q; e++) { String[] p = br.readLine().trim().split(" "); boolean isNum = p[0].equals("num"); if (p[1].equals("show")) { out.append(isNum ? nums.show() : words.show()).append('\n'); } else if (isNum) { int x = Integer.parseInt(p[2]); // "007"도 7로 읽힌다 if (p[1].equals("add")) nums.add(x); else nums.remove(x); } else { if (p[1].equals("add")) words.add(p[2]); else words.remove(p[2]); } } System.out.print(out); }}
C#Main.cs · 57 行
using System;using System.Collections.Generic;using System.IO;using System.Text;// 가장 최근 것부터 capacity개까지만 기억하는 목록. T가 무엇이든 같은 코드로 쓴다class Recent<T>{ private readonly List<T> items = new List<T>(); private readonly int capacity; // 제약 없는 T에는 ==를 쓸 수 없다(컴파일 오류). 그 T에 맞는 같음은 EqualityComparer가 안다 private static readonly EqualityComparer<T> Same = EqualityComparer<T>.Default; public Recent(int capacity) { this.capacity = capacity; } public void Add(T x) { Remove(x); items.Insert(0, x); if (items.Count > capacity) items.RemoveAt(items.Count - 1); } public void Remove(T x) { int i = items.FindIndex(y => Same.Equals(y, x)); if (i >= 0) items.RemoveAt(i); } public string Show() => items.Count == 0 ? "-" : string.Join(" ", items);}class Program{ static void Main() { var input = Console.In; string[] first = input.ReadLine()!.Trim().Split(' '); int k = int.Parse(first[0]), q = int.Parse(first[1]); var nums = new Recent<int>(k); // C# 제네릭은 int를 포장(boxing) 없이 담는다 var words = new Recent<string>(k); var sb = new StringBuilder(); for (int e = 0; e < q; e++) { string[] p = input.ReadLine()!.Trim().Split(' '); bool isNum = p[0] == "num"; if (p[1] == "show") sb.Append(isNum ? nums.Show() : words.Show()).Append('\n'); else if (isNum) { int x = int.Parse(p[2]); // "007"도 7로 읽힌다 if (p[1] == "add") nums.Add(x); else nums.Remove(x); } else if (p[1] == "add") words.Add(p[2]); else words.Remove(p[2]); } Console.Write(sb); }}
C++main.cpp · 59 行
#include <algorithm>#include <deque>#include <iostream>#include <sstream>#include <string>// 가장 최근 것부터 capacity개까지만 기억하는 목록. 템플릿이라 T마다 따로 만들어진다template <typename T>class Recent {public: explicit Recent(std::size_t capacity) : capacity_(capacity) {} void add(const T &x) { remove(x); items_.push_front(x); if (items_.size() > capacity_) items_.pop_back(); } void remove(const T &x) { auto it = std::find(items_.begin(), items_.end(), x); // T의 ==로 찾는다 if (it != items_.end()) items_.erase(it); } std::string show() const { if (items_.empty()) return "-"; std::ostringstream os; for (std::size_t i = 0; i < items_.size(); i++) os << (i ? " " : "") << items_[i]; return os.str(); }private: std::deque<T> items_; std::size_t capacity_;};int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::size_t k; int q; std::cin >> k >> q; Recent<long long> nums(k); // 수는 수로 읽어야 "007"과 "7"이 같아진다 Recent<std::string> words(k); std::string kind, cmd, arg; std::string out; for (int e = 0; e < q; e++) { std::cin >> kind >> cmd; if (cmd == "show") { out += (kind == "num" ? nums.show() : words.show()) + '\n'; continue; } std::cin >> arg; if (kind == "num") { long long x = std::stoll(arg); if (cmd == "add") nums.add(x); else nums.remove(x); } else { if (cmd == "add") words.add(arg); else words.remove(arg); } } std::cout << out;}