思想:
- 化整为零:将整个大队列的问题转化为多个小队列分开的问题,并使用一个主队列维护小队列编号。
- 隐含条件:每组数据不保证出队数=入队数,即每次读入前应清空队列
(另:queue不能clear(),故需deque)
从这个题里,也可以看到基本的查错方法。即首先寻找一般性问题(数组越界等),再思考题目限制(1.手算样例 2.认真读题)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<deque>
using namespace std;
const int MAXID=1e6;
int teamID[MAXID];
int getTeamID(int playerID){
return teamID[playerID];
}
bool isInMainQueue[MAXID];
bool isTeamInQueue(int teamID){//队伍是否在总队列里
return isInMainQueue[teamID];
}
deque<int> mainQueue;//存储队伍编号
void addTeamToQueue(int teamID){
if(!isInMainQueue[teamID])mainQueue.push_back(teamID);
isInMainQueue[teamID]=1;
}
deque<int> teamQueue[5000];//小组队列
void addPlayerToTeamQueue(int playerID){//将玩家加入到他自己的小组队伍中
int playerTeam=getTeamID(playerID);
teamQueue[playerTeam].push_back(playerID);
}
void addPlayerToMainQueue(int playerID){//将一个人加入到主队列中
int playerTeam=getTeamID(playerID);
if(!isTeamInQueue(playerTeam)){
addTeamToQueue(playerTeam);
}
addPlayerToTeamQueue(playerID);
}
int deTeamQueue(){//让第一个人出队 返回出队人编号
int firstTeamIndex=mainQueue.front();//第一个队伍编号
int nowFront=teamQueue[firstTeamIndex].front();//第一个人
if(teamQueue[firstTeamIndex].size()==1){
isInMainQueue[firstTeamIndex]=0;
mainQueue.pop_front();
}
teamQueue[firstTeamIndex].pop_front();
return nowFront;
}
void clearAll(){
memset(isInMainQueue,0,sizeof(isInMainQueue));
mainQueue.clear();
for(int i=0;i<=1020;i++){
teamQueue[i].clear();
}
}
char strTmp[100];
int main(){
int t=-1;
int cnt=0;
while(1){
cnt++;
clearAll();
scanf("%d",&t);
if(t==0)return 0;
for(int i=1;i<=t;i++){
int num;
scanf("%d",&num);
for(int j=1;j<=num;j++){
int playerID;
scanf("%d",&playerID);
teamID[playerID]=i;
}
}
cout<<"Scenario #"<<cnt<<endl;
while(1){
scanf("%s",&strTmp);
if(strTmp[0]=='E'){//插入
int playerID;
scanf("%d",&playerID);
addPlayerToMainQueue(playerID);
}else if(strTmp[0]=='D'){//出队
int playerID=deTeamQueue();
cout<<playerID<<endl;
}else if(strTmp[0]=='S'){//stop
cout<<endl;
break;
}
}
}
return 0;
}