我的PAT-ADVANCED代码仓:https://github.com/617076674/PAT-ADVANCED
原题链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805371602845696
题目描述:
题目翻译:
1095 校园里的车辆
浙江大学有8个校区和很多门。 从每个门我们可以收集进出门时间和穿过大门的车辆的车牌号码。 现在提供所有可用信息,你需要在任何特定时间点告知停放在校园内的汽车数量,并在一天结束时找到停放时间最长的汽车。
输入格式:
每个输入文件包含一个测试用例。每个测试用例开头包含两个正整数N(<= 10 ^ 4),代表记录数,以及K(<= 8 * 10 ^ 4)。代表查询数。接下来的N行,每行以下述形式给出一条记录:
plate_number hh:mm:ss status
plate_number是一个由英文大写字母和数字组成的7长度为7的字符串;hh:mm:ss代表一天中的时间点,一天中最早的时间是00:00:00,最迟的时间是23:59:59,status可能是in或out。
所有的时间都是在一天内的。每一条状态为in的记录按时间顺序和同一辆车的下一条out记录配对。任何没有与out记录配对的in记录都被忽略,同样任何没有与in配对的out记录都被忽略。题目保证在输入中至少有一个好的配对,且同一辆车不可能同时in和out。时间使用24小时制。
接下来的K行是查询行。每行以下述形式给出一个查询时间点:hh:mm:ss。注意,所有的查询点都是按时间顺序递增给出的(坑点来了:这句话至关重要,但是题目里却出现了拼写错误,accending应该是ascending)。
输出格式:
对每个查询点,在一行中输出此时停在校园里的汽车总量。最后一行输出在校园里停车时间最长的汽车的plat_number,如果有多辆汽车停车时间相同,则按字母序输出,每辆汽车以一个空格分隔。
输入样例:
16 7
JH007BD 18:00:01 in
ZD00001 11:30:08 out
DB8888A 13:00:00 out
ZA3Q625 23:59:50 out
ZA133CH 10:23:00 in
ZD00001 04:09:59 in
JH007BD 05:09:59 in
ZA3Q625 11:42:01 out
JH007BD 05:10:33 in
ZA3Q625 06:30:50 in
JH007BD 12:23:42 out
ZA3Q625 23:55:00 in
JH007BD 12:24:23 out
ZA133CH 17:11:22 out
JH007BD 18:07:01 out
DB8888A 06:30:50 in
05:10:00
06:30:50
11:00:00
12:23:42
14:00:00
18:00:00
23:59:00
输出样例:
1
4
5
2
1
0
1
JH007BD ZD00001 07:20:09
知识点:排序
思路:先按车的plat_number和时间排序筛选出合格的记录,再对记录按时间升序排序
(1)定义结构体类型record,记录单条记录的信息,即车辆的plat_number、记录产生的时刻(以秒为单位),以及记录类型。这里字符串用char[]型数组表示,因为string需要用cin和cout读入和写出,本题数据量过大,不可以用cin和cout。
(2)定义一个map<string, int> parkTime来记录每辆车在校园中停留的时长。
(3)将所有记录存于record allRecords[10000]数组中,然后将其按车牌号从小到大排序,若车牌号相同,则按时间值进行从小到大排序。
(4)遍历所有记录,查找有效记录,并将其存入record validRecords[10000]数组中。
由于有效记录必须是相邻的,因此如果当前遍历到的是i号记录,那么就判断它的车牌号和i + 1号记录的车牌号是否是同一个车牌号,并且是否满足i号的是“in”记录、i + 1号的是“out”记录。如果是,就说明这两条记录是有效记录,将它们均存入validRecords数组中,同时令这辆车的总停留时间parkTime[allRecords[i].plate_number]增加两条记录的时间之差,并更新记录最长总停留时间的变量maxTime。
(5)待把所有有效记录存入validRecords数组后,接下来应把valid数组按照时间顺序从小到大排序,然后进入查询阶段。由于查询的时间顺序是递增的,因此可以设置一个变量now,用以指向validRecords数组里面的记录,使得now指向的记录的时刻不超过本次欲查询的时刻;同时设置一个变量count,以记录当前校园内的车辆数。显然,当validRecords[now]为in时,count++;否则count--。这一步很重要,如果不这么做,而是对每个记录都从validRecords的首个元素开始查起,无法通过测试点4。
(6)遍历parkTime,输出总停留时间为maxTime的车辆plat_number和对应的时间。
C++代码:
#include<iostream>
#include<map>
#include<algorithm>
#include<string.h>
using namespace std;
struct record {
char plate_number[8];
int time; //以秒为单位的时间
char description[4];
};
int N, K;
record allRecords[10000];
record validRecords[10000];
int num = 0; //有效记录的条数
map<string, int> parkTime;
bool cmpByIdAndTime(record r1, record r2);
bool cmpByTime(record r1, record r2);
int changeToSecond(int hh, int mm, int ss);
int main() {
scanf("%d%d", &N, &K);
int hh, mm, ss, time;
for(int i = 0; i < N; i++) {
scanf("%s %d:%d:%d %s", allRecords[i].plate_number, &hh, &mm, &ss, allRecords[i].description);
time = changeToSecond(hh, mm, ss);
allRecords[i].time = time;
}
sort(allRecords, allRecords + N, cmpByIdAndTime);
int maxTime = 0;
for(int i = 0; i < N - 1; i++) {
if(strcmp(allRecords[i].plate_number, allRecords[i + 1].plate_number) == 0
&& strcmp(allRecords[i].description, "in") == 0 && strcmp(allRecords[i + 1].description, "out") == 0) {
parkTime[allRecords[i].plate_number] += allRecords[i + 1].time - allRecords[i].time;
if(parkTime[allRecords[i].plate_number] > maxTime){
maxTime = parkTime[allRecords[i].plate_number];
}
validRecords[num++] = allRecords[i];
validRecords[num++] = allRecords[i + 1];
}
}
sort(validRecords, validRecords + num, cmpByTime);
int now = 0;
int count = 0;
for(int i = 0; i < K; i++) {
scanf("%d:%d:%d", &hh, &mm, &ss);
int nowTime = changeToSecond(hh, mm, ss);
//由于查询时间是递增的,我们查询下一个时间的时候可以在前一个时间查询的计数基础上继续进行
while(now < num && validRecords[now].time <= nowTime){
if(strcmp(validRecords[now].description, "in") == 0){
count++;
}else{
count--;
}
now++;
}
printf("%d\n", count);
}
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;
}
bool cmpByIdAndTime(record r1, record r2) {
if(strcmp(r1.plate_number, r2.plate_number) == 0) {
return r1.time < r2.time;
} else {
return strcmp(r1.plate_number, r2.plate_number) < 0;
}
}
bool cmpByTime(record r1, record r2){
return r1.time < r2.time;
}
int changeToSecond(int hh, int mm, int ss) {
return hh * 60 * 60 + mm * 60 + ss;
}
C++解题报告: