考查点:模拟题,可以用优先队列
提交情况:第一次排队时候按列排搞错方向,第二次用优先队列push时候重复了,搞了半天,最后把优先队列单独push,最后是sorry的处理,跟题意理解有关,最后是没注意到出现队长相同的情况因为优先队列是不稳定排序的所以重载运算符的时候需要比较窗口号
思路:对于模拟题,首先要研究好样例,是怎么计算出来的,然后模拟计算过程,如果需要预处理的信息就开一个数组记录需要用到的信息。这道题,首先开一个窗口数组,但是每个窗口需要维护一个总时间和一个队列,在黄线外的客户需要选择最短的也就是每个窗口队列对头元素当前服务时间最小值,故可以用一个优先队列来维护队头元素的当前服务时间,这里关键在与队头服务时间的更新,因为出队后堆的每个元素都要减掉出对元素的服务时间,这里因为优先队列的值实际并没用到只要保持相对顺序即可,所以只需更新进入优先队列新元素的服务时间值,在开一个数组记录每个客户的时间即可
#define LOCAL
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#define FOR(i, x, y) for(int i = x; i <= y; i++)
#define rFOR(i, x, y) for(int i = x; i >= y; i--)
#define MAXN 1010
#define oo 0x3f3f3f3f
using namespace std;
struct window{
queue<int> q;
int w;
}ww[30];
struct first{
int time;
int wi;
bool operator<(const first& a)const{
if(a.time<time) return true;
else if(a.time==time && a.wi<wi) return true;
else return false;
}
}ft;
priority_queue<first> fq;
int proc[MAXN];
int first[30];
int ans[MAXN];
int main()
{
#ifdef LOCAL
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
#endif // LOCAL
int n,m,k,q;
scanf("%d%d%d%d",&n,&m,&k,&q);
FOR(i,1,k)
scanf("%d",&proc[i]);
int cnt=1;
FOR(j,1,m)
{
FOR(i,1,n)
{
ww[i].q.push(cnt);
ww[i].w+=proc[cnt];
ans[cnt]=ww[i].w;
cnt++;
}
}
FOR(i,1,n){
int t=ww[i].q.front();
ft.time=proc[t];
ft.wi=i;
fq.push(ft);
}
while(cnt<=k){
int wi=fq.top().wi;
int ti =fq.top().time;
fq.pop();
ww[wi].q.pop();
ww[wi].q.push(cnt);
int tt=ww[wi].q.front();
tt=proc[tt];
ww[wi].w+=proc[cnt];
ans[cnt]=ww[wi].w;
ft.wi=wi;
ft.time= ti +tt;
fq.push(ft);
int w1=fq.top().wi;
int ti1 =fq.top().time;
cnt++;
}
FOR(i,1,q)
{
int id;
scanf("%d",&id);
int aa=ans[id];
if(aa-proc[id]>=540) printf("Sorry\n");
else{
printf("%02d:%02d\n",aa/60+8,aa%60);
}
}
return 0;
}