题目大意:
给出N条记录,每条记录给出一辆车的车牌号,当前时刻以及入校情况(入校还是出校)。
然后给出K个查询,每个查询给出一个时刻,输出在这个时刻内校园的车辆数。
查询完毕后输出在学校内停留时间最长的车辆的车牌号和对应的停留时间(如果有多个就一并输出)
同一辆车,配对的on和off必须满足在把这辆车按时间顺序排列后,在他们之间不允许出现其他的on或者off的记录,否则视为无效记录。
这个题考到时间的处理,有效记录的处理([PAT-A 1016]的通话记录也有相同的点)。
思路:
*时间统一转换为以秒为单位,方便处理。
1)定义结构体类型Car,记录单条的信息,即车辆的车牌号,记录产生的时刻,以及记录类型(in/out)。
定义两个Car数组,all存放所有信息,valid存放有效信息。
2)定义map<stirng,int>parkTime,存放每一辆车的停放时间。
3)将所有记录存放在all数组,然后将其按按照车牌号从小到大排序,若车牌号相同,则按照时间值的从小到大排序。
4)遍历所有记录,找见所有有效记录。
由于有效记录必须是相邻的,所以如果当前遍历到的是i号记录,那么就判断它的车牌号和i+1号记录是否是一个车牌号
同时i号记录的是in记录,那么i+1号是否是out记录,如果是,则这两条记录时有效记录,将它们存入Vaild数组。
同时令这辆车的总停留时间parkTime[all[i].id]增加两个记录的时间之差,并更新记录最长的停留时间。
5)将所有有效的记录都存入Vaild数组后,接下来应该把vaild数组按照时间大小从小到大排序,然后进入查询阶段。
题目中给出查询的时刻按时间递增,设置变量now,用以指向vaild数组里面的记录,使得now指向的记录不超过本次欲查询的时刻。
同时设置一个变量numCar,用以记录当前校园内的车辆数,此前记录为in,numCar++,为out,numCar–。
6)遍历parkTime,输出停留时间等于maxTime的车辆的车牌号和对应时间。
AC代码:
//PAT_A 1095
#include<cstdio>
#include<cstring>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
const int maxn = 10010;
struct Car {
char id[18];//车牌号
int time;//时间都转化成秒 00:00:00记为0
char status[4];
}all[maxn], vaild[maxn];
int num = 0;//有效记录的条数
map<string, int>parkTime;
int timeToInt(int hh, int mm, int ss) {
return hh * 3600 + mm * 60 + ss;
}
bool cmpByIdAndTime(Car a, Car b) {//按车牌号排序,否则按时间大小
if (strcmp(a.id, b.id) != 0)return strcmp(a.id, b.id) < 0;
else return a.time < b.time;
}
bool cmpByTime(Car a, Car b) {//按时间大小排序
return a.time < b.time;
}
int main() {
int n, k, hh, mm, ss;
int maxTime = -1;//最长总停留时间
(void)scanf("%d %d", &n, &k);
for (int i = 0; i < n; i++) {
(void)scanf("%s %d:%d:%d %s", all[i].id, &hh, &mm, &ss, all[i].status);
all[i].time = timeToInt(hh, mm, ss);
}
sort(all, all + n, cmpByIdAndTime);
for (int i = 0; i < n - 1; i++) {
if ((strcmp(all[i].id, all[i + 1].id) == 0) &&//判断有效记录,相邻两个记录是同一车牌,且前一个为'on',后一个为'out'
(strcmp(all[i].status, "in") == 0) &&
(strcmp(all[i + 1].status, "out") == 0)) {
vaild[num++] = all[i];
vaild[num++] = all[i + 1];
int inTime = all[i + 1].time - all[i].time;
if (parkTime.count(all[i].id) == 0) {//如果map中还没有这个车牌号,置0。
parkTime[all[i].id] = 0;
}
parkTime[all[i].id] += inTime;
if (parkTime[all[i].id] > maxTime)maxTime = parkTime[all[i].id];//更新最大总停留时间
}
}
sort(vaild, vaild + num, cmpByTime);//有效记录按时间大小排序
int now = 0, numCar = 0;//now指向不超过当前查询时间的记录,numCar记录当前由多少辆车
for (int i = 0; i < k; i++) {
(void)scanf("%d:%d:%d", &hh, &mm, &ss);
int time = timeToInt(hh, mm, ss);
while (now < num && vaild[now].time <= time) {
if (strcmp(vaild[now].status, "in") == 0)numCar++;
else numCar--;
now++;//处理下一条记录。
}
printf("%d\n", numCar);
}
map<string, int>::iterator it;
for (it = parkTime.begin(); it != parkTime.end(); it++) {
if (it->second == maxTime) {
printf("%s ", it->first.c_str());
}
}
printf("%02d:%02d:%02d\n", maxTime / 3600, maxTime % 3600 / 60, maxTime % 60);//最长时间
return 0;
}