题目大意:
题目链接:http://poj.org/problem?id=2259
有
t
t
个团队的人正在排一个长队。每次新来一个人时,如果他有队友在排队,那么新人会插队到最后一个队友的身后。如果没有任何一个队友排队,则他会被排到长队的队尾。
要求支持如下3中指令:
-
x
x
:编号为的人进入长队。
- DEQUEUE D E Q U E U E :长队的队首出队。
- STOP S T O P :停止模拟
对于每个 DEQUEUE D E Q U E U E 指令,输出出队的人的编号。
思路:
很明显的队列。但是插队操作却有点难实现。
为了完成插队操作,就要先建 n+1 n + 1 个队列。 q[0] q [ 0 ] 用来储存团队的排队情况(因为一个团队会在一起),而 q[1] q [ 1 ] 到 q[n] q [ n ] 则储存每个团队的人员情况。
每当来了一个人时,就判断这个人的是否有队友在队伍中,如果有,就 q[team[x]].push(x) q [ t e a m [ x ] ] . p u s h ( x ) 进入团队队列;如果没有,就先将这个团队进入总队列 q[0].push(team[x]) q [ 0 ] . p u s h ( t e a m [ x ] ) ,再讲这个人进入团队队列 q[team[x]].push(x) q [ t e a m [ x ] ] . p u s h ( x ) 。出队时,如果出队的人 x x 还有队友在队伍中,那么就直接将从团队队列中退出 q[team[x]].pop() q [ t e a m [ x ] ] . p o p ( ) ;如果没有队友了,那么不仅要然他从团队中退出,而且还要将整个团队从总队列退出 q[0].pop() q [ 0 ] . p o p ( ) 。
代码:
#include <cstdio> #include <queue> #include <cstring> #include <string> #include <iostream> using namespace std; int n,m,team[1000001],x,sum; string s; int main() { while (++sum) { scanf("%d",&n); if (!n) return 0; printf("Scenario #%d\n",sum); queue<int> q[1011]; //空间换时间 memset(team,0,sizeof(team)); for (int i=1;i<=n;i++) { scanf("%d",&m); for (int j=1;j<=m;j++) { scanf("%d",&x); team[x]=i; } } while (1) { cin>>s; if (s[0]=='S') break; if (s[0]=='E') { scanf("%d",&x); if (!q[team[x]].size()) //没有队友 q[0].push(team[x]); q[team[x]].push(x); } if (s[0]=='D') { printf("%d\n",q[q[0].front()].front()); //输出 q[q[0].front()].pop(); if (!q[q[0].front()].size()) //没有队友了 q[0].pop(); } } printf("\n"); } }