#include <iostream>
#include <queue>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
struct Player
{
int arrive_time, play_time;
int start_time, waiting_time;
bool operator<(const Player &p1)const//sort排序
{
if (start_time != p1.start_time) return start_time < p1.start_time;
return arrive_time < p1.arrive_time;
}
bool operator>(const Player &p1)const//优先队列中比较大小
{
return arrive_time > p1.arrive_time;
}
};
struct Table
{
int id;
int fin_time;
bool operator>(const Table &t1)const//优先队列中比较大小
{
if (fin_time != t1.fin_time) return fin_time > t1.fin_time;
return id > t1.id;
}
};
priority_queue<Player, vector<Player>, greater<Player>> normal_player, vip_player;
priority_queue<Table, vector<Table>, greater<Table>> normal_table, vip_table;
const int N = 110, INF = 0x3f3f3f3f;
bool is_vip[N];
int serve_cnt[N];
vector<Player> player;
int dateToInt(int hh, int mm, int ss) {
return hh * 3600 + mm * 60 + ss;
}
void printDate(int t) {
printf("%02d:%02d:%02d", t / 3600, t % 3600 / 60, t % 60);
}
void assign(priority_queue<Player, vector<Player>, greater<Player>>& ps,
priority_queue<Table, vector<Table>, greater<Table>>& ts) {
auto p = ps.top(); ps.pop();
auto t = ts.top(); ts.pop();
int wait_time = t.fin_time - p.arrive_time;
p.start_time = t.fin_time;
p.waiting_time = round(wait_time / 60.0);
serve_cnt[t.id]++;
player.push_back(p);
ts.push({ t.id,t.fin_time + p.play_time });
}
int main() {
int n;
cin >> n;
//避免在下面top或者pop的时候还要额外的做出判断,这里插入一个不可能取到的值
vip_player.push({ INF }); normal_player.push({ INF });
while (n--)
{
int hh, mm, ss, p, tag;
scanf("%d:%d:%d %d %d", &hh, &mm, &ss, &p, &tag);
p = min(p, 120);
p *= 60;
int t = dateToInt(hh, mm, ss);
if (tag == 1) vip_player.push({ t,p });
else normal_player.push({ t,p });
}
int k, m;
cin >> k >> m;
for (int i = 0; i < m; i++) {
int x;
cin >> x;
is_vip[x] = true;
}
//避免在下面top或者pop的时候还要额外的做出判断,这里插入一个不可能取到的值
normal_table.push({ -1,INF }); vip_table.push({ -1,INF });
for (int i = 1; i <= k; i++) {
if (is_vip[i]) vip_table.push({ i,8 * 3600 });
else normal_table.push({ i,8 * 3600 });
}
while (normal_player.size() > 1 || vip_player.size() > 1)
{
auto np = normal_player.top();//普通玩家
auto vp = vip_player.top();//vip玩家
int arrive_time = min(np.arrive_time, vp.arrive_time);
//把普通球台和vip球台到达的时间都设置为优先到达的玩家时间,这样一直让玩家维持在队列中的形态,
//由于设置的是最先到达的玩家,所以不用担心这样算起来玩家的等待时间会有问题,因为其他玩家还没到呢,是不能算等待
//时间的。
while (normal_table.top().fin_time < arrive_time)
{
auto t = normal_table.top();
normal_table.pop();
t.fin_time = arrive_time;
normal_table.push(t);
}
while (vip_table.top().fin_time < arrive_time)
{
auto t = vip_table.top();
vip_table.pop();
t.fin_time = arrive_time;
vip_table.push(t);
}
auto nt = normal_table.top();
auto vt = vip_table.top();
int end_time = min(nt.fin_time, vt.fin_time);
if (end_time >= 21 * 3600) break;//如果连此时最早服务完的人都超过21点了那就直接break掉吧
if (vp.arrive_time <= end_time && end_time == vt.fin_time) assign(vip_player, vip_table);//如果现在vip球桌空出且队列中有vip球员,则vip先上
else if (np.arrive_time < vp.arrive_time) {//如果普通人先到
//注意这里的nt是table类型的,我们重载了它的>,所以他会先比较结束时间,谁先结束谁先分配,然后在比较idx,谁id小谁先分配
if (nt > vt) assign(normal_player, vip_table);
else assign(normal_player, normal_table);
}
else {//vip球员先到
if (nt > vt) assign(vip_player, vip_table);
else assign(vip_player, normal_table);
}
}
sort(player.begin(), player.end());
for (int i = 0; i < player.size(); i++) {
printDate(player[i].arrive_time);
printf(" ");
printDate(player[i].start_time);
printf(" %d\n", player[i].waiting_time);
}
cout << serve_cnt[1];
for (int i = 2; i <= k; i++) cout << " " << serve_cnt[i];
return 0;
}