--- title: "小组队列" created: 2025-11-28 tags: - 算法 --- # 小组队列 ## 题目 有 n 个小组要排成一个队列,每个小组中有若干人。 当一个人来到队列时,如果队列中已经有了自己小组的成员,他就直接插队排在自己小组成员的后面,否则就站在队伍的最后面。 请你编写一个程序,模拟这种小组队列。 输入格式: 输入将包含一个或多个测试用例。 对于每个测试用例,第一行输入小组数量 t。 接下来 t 行,每行输入一个小组描述,第一个数表示这个小组的人数,接下来的数表示这个小组的人的编号。 编号是 0 到 999999 范围内的整数。 一个小组最多可包含 1000 个人。 最后,命令列表如下。 有三种不同的命令: 1、`ENQUEUE x` - 将编号是 x 的人插入队列; 2、`DEQUEUE` - 让整个队列的第一个人出队; 3、`STOP` - 测试用例结束 每个命令占一行。 当输入用例 t=0 时,代表停止输入。 需注意:测试用例最多可包含 200000(20 万)个命令,因此小组队列的实现应该是高效的: 入队和出队都需要使用常数时间。 输出样例 对于每个测试用例,首先输出一行 `Scenario #k`,其中 k 是测试用例的编号。 然后,对于每个 `DEQUEUE` 命令,输出出队的人的编号,每个编号占一行。 在每个测试用例(包括最后一个测试用例)输出完成后,输出一个空行。 数据范围 1≤t≤1000 输入样例: ```text 2 3 101 102 103 3 201 202 203 ENQUEUE 101 ENQUEUE 201 ENQUEUE 102 ENQUEUE 202 ENQUEUE 103 ENQUEUE 203 DEQUEUE DEQUEUE DEQUEUE DEQUEUE DEQUEUE DEQUEUE STOP 2 5 259001 259002 259003 259004 259005 6 260001 260002 260003 260004 260005 260006 ENQUEUE 259001 ENQUEUE 260001 ENQUEUE 259002 ENQUEUE 259003 ENQUEUE 259004 ENQUEUE 259005 DEQUEUE DEQUEUE ENQUEUE 260002 ENQUEUE 260003 DEQUEUE DEQUEUE DEQUEUE DEQUEUE STOP 0 ``` 输出样例: ```text Scenario #1 101 102 103 201 202 203 Scenario #2 259001 259002 259003 259004 259005 260001 ``` ## 思路分析 这是一道非常简单的题目,但是输入太恶心……没必要 看思路就行 在任何时刻,同一个小组的人只要来到了队伍,就会站在一起, 所以建立一个队列 $q\_0$ 存储队伍中所有小组的编号, 再为每个小组 i 建立一个队列 $q\_i $ 存储队伍中这个小组的所有成员, 一共 n+1个队列 当一个编号为 x,组号为 y的人来到队伍时,我们直接把 x插入 $q\_y $ 末尾。 如果在插入之前 $q\_y $ *是空的,则还要把 y插到* $q\_0$ 末尾,表明队伍最后出现了一个新的小组。 当接受到出队指令时,我们通过 $q\_0$ *得知排在最前面的小组组号 y,然后再把* $q\_y$ 的对头出队。 出队后如果$q\_y$ *为空,就从* $q\_0$ 开头删除 y,表明这个小组目前所有人已经离开。 有点想用邻接表似的二维队列来做 但会更麻烦 ## 代码实现 ```cpp #include using namespace std; const int N = 1010, M = 1000010; int teamid[M]; int main() { int n, C = 1; while (cin >> n, n) { queue team; queue person[N]; printf("Scenario #%d\n", C ++ ); for (int i = 0; i < n; i ++ ) { int cnt; cin >> cnt; while (cnt -- ) { int x; cin >> x; teamid[x] = i; } } string command; while (cin >> command, command != "STOP") { if (command == "ENQUEUE") { int x; cin >> x; int tid = teamid[x]; if (person[tid].empty()) team.push(tid); person[tid].push(x); } else { int tid = team.front(); auto &q = person[tid]; cout << q.front() << endl; q.pop(); if (q.empty()) team.pop(); } } cout << endl; } return 0; } ``` ## 同类题型 ## 视频讲解 --- ⬅️ [[2-Learning/02-算法/03-刷题理模型/栈与队列相关模型/队列/品种临近|品种临近]] 🏠 [[00-刷题理模型]] ➡️ [[机器翻译|机器翻译]]