一、概述
根据一天中不同时刻车辆的进出情况,输出某时刻校园内的车辆总数和在一天中在校园内呆的时间最长的车辆。
本题实际上是两道题的集合,与之前的电话费题目类似,都是要先找出合法配对再往下做。
小的坑很多,要注意。
二、分析
首先要明确一点,将时间全化为秒会好做很多,不然时分秒比较谁先谁后逻辑太麻烦了。另外本题对于运行时间较敏感,姥姥可能真拿了八万条数据来测试也说不好,少用cin和cout。
利用结构体储存出入记录。如下:
struct Car
{
string plate_number;
int time;
int InorOut;
int valid = 0;
}car[10010];
出入记录有合法的,有非法的,对于非法记录,视为无效。那么首先要把有效记录找出来。如果之前做过计算话费的题目,那就简单的多:首先以车牌号为第一优先,时间为第二优先将所有记录进行排序,然后从头开始遍历,找出所有的车牌号相同,且时间相邻,一进一出的记录,这两条都是合法记录,将其valid置为1,这样完成了数据清洗工作。与此同时还可以求出各辆车在学校呆的总时间。如下:
cmp函数
bool cmpcar(Car a, Car b)
{
int s = a.plate_number.compare(b.plate_number);
if (s != 0)
return s < 0;
else
return a.time < b.time;
}
数据清洗
sort(car, car + N, cmpcar);
int sumtime = 0;
for (i = 0; i < N; i++)
{
if (car[i].plate_number.compare(car[i + 1].plate_number) == 0)
{
if (car[i].InorOut == 1 && car[i + 1].InorOut == 0)
{
sumtime = sumtime + car[i + 1].time - car[i].time;
car[i].valid = 1;
car[i + 1].valid = 1;
}
}
else
{
mp[car[i].plate_number] = sumtime;
sumtime = 0;
}
}
在将车辆与呆的总时间进行对应时,选择map较好,将string类型的车牌号与int类型的时间相对应,很方便,只不过map的按键递增没有用上,注意不能把时间当做键值,因为键值唯一,而车牌号可能有多个,把时间当做键值则只有一个车牌号会输出。
这里有极重要的一点:如果map是在main里面声明的,会导致测试点一和测试点二报段错误!!原因和在main里面开一个超大数组效果差不多,都是因为爆栈了,map的元素过多导致main受不了。
然后是计算某个时间点之前的车辆数量。注意到题目中有说明,测试时间点是递增的,这句话很重要,不会无缘无故加一条条件的,这点说明,我们不必每次都从00:00:00开始遍历相加,而是可以从上一个测试点开始往下加,节约无数时间。如下:
sort(car, car + N, cmptime);
int k = 0;
int carnum = 0;//这个写在里面会导致超时
for (i = 0; i < K; i++)
{
int H, M, S;
scanf("%d:%d:%d", &H, &M, &S);
int Time = H * 3600 + M * 60 + S;
while (car[k].time <= Time)
{
if (car[k].valid == 1)
{
if (car[k].InorOut == 1)
carnum++;
else
carnum--;
}
k++;
}
printf("%d\n", carnum);
}
然后输出即可。
三、总结
本题关键之处便在于利用好测试时间点的递增特性。
总结一下遇到的导致PAT段错误的原因吧:
main里面开大数组:简而言之就是在main里面声明了一个很大,或者可以不断递增的数组。很可能会段错误。
数组下标溢出:常出现于四万个元素刚好开个四万的数组,不妨开个五万的留有余量。
cmp函数:用>=代替>据说会导致段错误,但我还没遇到。
指针异常:这个就更少了,很少单独控制指针,太容易晕了。
PS:代码如下:
#include<stdio.h>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
struct Car
{
string plate_number;
int time;
int InorOut;
int valid = 0;
}car[10010];
map<string, int> mp;
map<string, int>::iterator it;
bool cmpcar(Car a, Car b)
{
int s = a.plate_number.compare(b.plate_number);
if (s != 0)
return s < 0;
else
return a.time < b.time;
}
bool cmptime(Car a, Car b)
{
return a.time < b.time;
}
int main()
{
int N, K;
scanf("%d %d", &N, &K);
int i;
for (i = 0; i < N; i++)
{
cin >> car[i].plate_number;
int hh, mm, ss;
scanf("%d:%d:%d", &hh, &mm, &ss);
car[i].time = hh * 3600 + mm * 60 + ss;
string ioo;
cin >> ioo;
if (ioo.compare("in") == 0)
car[i].InorOut = 1;
else
car[i].InorOut = 0;
}
car[i].plate_number = "-1";
car[i].time = 0;
sort(car, car + N, cmpcar);
int sumtime = 0;
for (i = 0; i < N; i++)
{
if (car[i].plate_number.compare(car[i + 1].plate_number) == 0)
{
if (car[i].InorOut == 1 && car[i + 1].InorOut == 0)
{
sumtime = sumtime + car[i + 1].time - car[i].time;
car[i].valid = 1;
car[i + 1].valid = 1;
}
}
else
{
mp[car[i].plate_number] = sumtime;
sumtime = 0;
}
}
/
sort(car, car + N, cmptime);
int k = 0;
int carnum = 0;//这个写在里面会导致超时
for (i = 0; i < K; i++)
{
int H, M, S;
scanf("%d:%d:%d", &H, &M, &S);
int Time = H * 3600 + M * 60 + S;
while (car[k].time <= Time)
{
if (car[k].valid == 1)
{
if (car[k].InorOut == 1)
carnum++;
else
carnum--;
}
k++;
}
printf("%d\n", carnum);
}
int maxnum = 0;
int max = 0;
for (it = mp.begin(); it != mp.end(); it++)
{
if (it->second > max)
max = it->second;
}
for (it = mp.begin(); it != mp.end(); it++)
{
if (it->second == max)
cout << it->first << " ";
}
printf("%02d:%02d:%02d", max / 3600, max % 3600 / 60, max % 60);
return 0;
}