题目:
Zhejiang University has 8 campuses and a lot of gates. From each gate we can collect the in/out times and the plate numbers of the cars crossing the gate. Now with all the information available, you are supposed to tell, at any specific time point, the number of cars parking on campus, and at the end of the day find the cars that have parked for the longest time period.
Input Specification:
Each input file contains one test case. Each case starts with two positive integers N (≤10000), the number of records, and K (≤80000) the number of queries. Then N lines follow, each gives a record in the format:
plate_number hh:mm:ss status
where plate_number is a string of 7 English capital letters or 1-digit numbers; hh:mm:ss represents the time point in a day by hour:minute:second, with the earliest time being 00:00:00 and the latest 23:59:59; and status is either in or out.
Note that all times will be within a single day. Each in record is paired with the chronologically next record for the same car provided it is an out record. Any in records that are not paired with an out record are ignored, as are out records not paired with an in record. It is guaranteed that at least one car is well paired in the input, and no car is both in and out at the same moment. Times are recorded using a 24-hour clock.
Then K lines of queries follow, each gives a time point in the format hh:mm:ss. Note: the queries are given in ascending order of the times.
Output Specification:
For each query, output in a line the total number of cars parking on campus. The last line of output is supposed to give the plate number of the car that has parked for the longest time period, and the corresponding time length. If such a car is not unique, then output all of their plate numbers in a line in alphabetical order, separated by a space.
Sample Input:
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
Sample Output:
1
4
5
2
1
0
1
JH007BD ZD00001 07:20:09
思路分析:
1、对于题目中记录的保存:题目中要求对于每辆车按照时间大小进行记录,对于存在 pair <in, out> 的记录才保存至车辆有效信息中。(具体实现:用 record 数组对初始的记录进行保存,对于数组进行按照车牌号和车进出时间进行排序,即 Compare 函数,从中筛选出准确的记录保存到车辆信息中)。
2、对于时间的存储,由于后面需要不断进行时间大小的比较,用字符串不方便,用单一的小时,分钟,秒钟在比较方面也比较麻烦,作者在此采用统一将题目中出现的各种时间全部转换为一天之中的秒钟数,方便大小比较。
3、题目中要求输出各个时间点车的数量,用 countCar 数组进行每个时间点车数量的保存。
4、题目后面输出的是全天中停放时间最长的车辆的车牌号以及停放时长,不可仅以刚才的 car 数组中的时长进行简单比较。此处,用一个 map 用于记录不同车辆全天中的停车时长,对于输出的车牌号顺序问题,由于 map 底层是用红黑树实现的,本身是有序的,所以直接进行顺序遍历输出即可。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <vector>
#include <map>
using namespace std;
const int MAX_N = 10010; //记录最大值
const int MAX_K = 80010; //查找次数的最大值
struct Record{
string carId; //车牌号
int time; //车辆进入或者出去的时间,用秒数表示
bool status; //true为进入,false为退出
};
struct Car{
string carId; //车牌号
int inTime; //进入时间
int outTime; //出去时间
int stopTime; //以秒为单位,保存本次停车的总停留时间
Car(string id, int intime, int outtime, int stoptime): carId(id), inTime(intime), outTime(outtime), stopTime(stoptime){}
};
Record record[MAX_N]; //用于存储输入的各个记录
vector<Car> car; //用于存储车辆的一次停车记录,包括进入和出去
int query[MAX_K]; //记录要查询的时间
int countCar[MAX_K]; //每个时间点停车场内车辆个数
map<string, int> carTime; //记录每辆车在全天内停车的总秒数
//进行对记录的排序》》按照车牌号从小到大》》车牌号相同,按照时间从小到大
bool Compare(Record a, Record b){
if(a.carId == b.carId){
return a.time < b.time;
}
else{
return a.carId < b.carId;
}
}
//将 hour::minute::second 转换为以秒表示的时间
int timeToSecond(int hour, int minute, int second){
return hour * 3600 + minute * 60 + second;
}
int main(){
int n, k;
scanf("%d%d", &n, &k);
//输入记录信息
string status;
int hour, minute, second;
for(int i = 0; i < n; ++i){
cin >> record[i].carId;
scanf("%d:%d:%d", &hour, &minute, &second);
record[i].time = timeToSecond(hour, minute, second);
cin >> status;
if(status == "in"){
record[i].status = true;
}
else{
record[i].status = false;
}
}
//输入查询信息
for(int i = 0; i < k; ++i){
scanf("%d:%d:%d", &hour, &minute, &second);
int time = timeToSecond(hour, minute, second);
query[i] = time;
countCar[i] = 0;
}
//对记录进行排序
sort(record, record + n, Compare);
int longTime = 0; //车辆最长停放时间保存在该变量中
//对于有效的记录,将其记录到car这个记录中
for(int i = 0; i < n; ++i){
if(record[i].carId == record[i + 1].carId && record[i].status == true && record[i + 1].status == false){
int time1 = record[i].time;
int time2 = record[i + 1].time;
int time = time2 - time1;
car.push_back(Car(record[i].carId, time1, time2, time));
//对每辆车进行全天停放时间的统计
carTime[record[i].carId] += time;
if(carTime[record[i].carId] > longTime){
longTime = carTime[record[i].carId];
}
}
}
//进行查询
for(int i = 0; i < car.size(); ++i){
int time1 = car[i].inTime;
int time2 = car[i].outTime;
for(int j = 0; j < k; ++j){
int time = query[j];
//统计在该时间点,在停车场中的车辆数目
if(time1 <= time && time2 > time){
countCar[j]++;
}
}
}
//输出各个时间点内车辆数目
for(int i = 0; i < k; ++i){
printf("%d\n", countCar[i]);
}
hour = longTime / 3600;
minute = longTime % 3600 / 60;
second = longTime % 60;
//输出最长停车时间的车的车牌号
for(map<string, int>::iterator it = carTime.begin(); it != carTime.end(); ++it){
if(it->second == longTime){
cout << it->first << " ";
}
}
printf("%02d:%02d:%02d", hour, minute, second);
return 0;
}
总结:
1、对于该题目中进出时间的问题,起初我纠结了好几次到底是用 string 存储时间呢,还是用小时分钟秒钟直接存。两者都有利弊,最后想到用秒钟存还是最方便的一种。
2、第二,就是输出最长停车时长车辆的问题。刚开始一直用 car 数组中的时长进行输出,调试了好久~。最后发现,题目中要求的是全天停车时长。