题意:
有 n
个小组 要进行排队,每个小组中有若干个人。
当一个人来到队伍时,
- 如果 队伍中已经有自己小组的成员,他就直接插队排在自己小组成员的后面。
- 否则,就站在队伍的最后面。
给定 不超过 2 * 10 ^ 5
个入队指令(编号为 X
的人 来到队伍)和 出队指令(队头的人 出队),输出 出队的顺序。
思路:
这题显然需要用到很多 小队列,因此为了方便,我们先直接开 N
个 queue
作为 总队列,即 queue<int>[N]
用一个 哈希表 ha
,记录 所有输入的成员编号 所属的 小组编号。
用一个 数组 st
,记录 输入成员所属的小组 是否出现在 总的队列 中,如果 为 0
则未出现过,不为 0
则同时记录 该小组 出现在 第几段 小队列 之中。
之后就是模拟,具体详见代码。
注意:
- 出队 的时候,当 某个小队列的大小为
0
一定要记得将st
数组 对应处 清0
。
代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
map<int, int> ha;//成员编号对应的组别编号
int st[N];//判断有无某个组别的成员出现在队列中,同时记录该组别在第几组小队列中
int main()
{
int T = 1;
int Cnt = 0;
while (~scanf("%d", &T), T)
{
queue<int> qq[N];
memset(st, false, sizeof st);
ha.clear();
int h = 1, t = 0;
while (T--)
{
int cnt; scanf("%d", &cnt);
++t;
for (int i = 0; i < cnt; ++i)
{
int tag; scanf("%d", &tag);
ha[tag] = t;
}
}
char op[20];
h = 1, t = 0;
printf("Scenario #%d\n", ++Cnt);
while (~scanf("%s", op), *op != 'S')
{
if (*op == 'E')
{
int x; scanf("%d", &x);
//cout << "ha[x] " << ha[x] << '\n';
//当总队列中还没有 x 所属组别的成员,则开一个新的小队列并压入 x
if (!st[ha[x]])
{
st[ha[x]] = ++t;
qq[t].push(x);
}
else //否则压入他所属组别的小队列
{
qq[st[ha[x]]].push(x);
}
}
else
{
if (qq[h].size())
{
int top = qq[h].front();
printf("%d\n", top);
qq[h].pop();
if (!qq[h].size())
{
st[ha[top]] = 0;
h++;
}
}
}
}
puts("");
}
return 0;
}