小组队列

小组队列

有n个小组,第i个小组有\(t_i\)个人,并且给出每个小组的人的标号,请维护一个队列,支持一些操作

ENQUEUE x:让编号是x的人插入队列,如果队列中存在x的所属小组,那么x直接插队到所属小组的队列的最后一个位置。

DEQUEUE:让队首的人出队,并输出他的编号。

STOP:所有操作结束

\(n\leq 1000\),一个小组最多1000人,编号不超过\(999999\)

显然我们需要每项操作都在\(O(1)\)的时间复杂度下。

为了快速查询所在小组的队列,显然利用桶排的思想,设\(Q_i\)表示第i组的队列,显然\(i=1,2,...,n\)

问题在于如何确定队首的小组,于是我们再开了一个队列,用来保存每个组顺序,特别地把这个小组定义为\(Q_0\)

那么对于操作ENQUEUE x,将其插入其小组队列末尾,如果插入前小组队列为空,顺便还要将其小组的编号入队\(Q_0\)

对于操作DEQUEUE,根据\(Q_0\)的队首的找到小组i,根据\(Q_i\)的队首找到人\(j\),j出队,如果j出队后,其所属小组的队列为空,\(Q_0\)队首出队。

人人都说此题简单,但是我没想到。

参考代码:

#include <iostream>
#include <cstdio>
#include <queue>
#define il inline
#define ri register
using namespace std;
int be[1000000];
queue<int>Q[1001];
int main(){int t,s,lsy(0);char M[8];
	while(scanf("%d",&t),t){
		int i,j;for(i=1;i<=t;++i){
			scanf("%d",&s);
			while(s--)scanf("%d",&j),be[j]=i;
		}for(i=0;i<=t;++i)
			 while(Q[i].size())Q[i].pop();
		printf("Scenario #%d\n",++lsy);
		while(scanf("%s",M),M[0]!='S'){
			if(M[0]=='E'){scanf("%d",&i);
				if(Q[be[i]].empty())Q[0].push(be[i]);
				Q[be[i]].push(i);
			}
			else if(M[0]=='D'){
				printf("%d\n",Q[Q[0].front()].front());
				Q[Q[0].front()].pop();
				if(Q[Q[0].front()].empty())Q[0].pop();
			}
		}putchar('\n');
	}
	return 0;
}

posted @ 2019-07-24 10:19  a1b3c7d9  阅读(260)  评论(0编辑  收藏  举报