A1095
思路
此题由于时间限制,必须使用map映射才能通过测试点4,但思路与A1016基本一致,随后会更新map的方法
声明records结构体,按车牌号,时间先后顺序排序。随后标记其中的有效记录(in与out相邻),并在有效记录中统计数量(是有效记录并且满足时间这个条件),计算时间
注意点
1、一辆车多次进入时间停留,其在校园内的时间会累加
2、将时间转换为以秒为单位会方便比较
代码
#include <bits/stdc++.h>
using namespace std;
int N, K;
int maxAns;
int cars[5005];//以records的id为下标,记录某辆车总共停留的时间
struct records{
char num[15];
int hh, mm, ss;
int time;//以秒为单位方便比较询问的时间点
int maxTime;
int id;//便于cars数组的散列进行累加
bool status;//true:in;false:out
bool valid;//此条记录是否有效,true有效
records(){}
}rec[10005];
bool cmpTime(records r1, records r2)
{
if(strcmp(r1.num, r2.num))
{
return strcmp(r1.num, r2.num) < 0;
}
else if(r1.hh != r2.hh)
{
return r1.hh < r2.hh;
}
else if(r1.mm != r2.mm)
{
return r1.mm < r2.mm;
}
else
{
return r1.ss < r2.ss;
}
}
bool judge(int i, int t)//判断该车在这个时间点是否在校园内
{
records start = rec[i];
records endd = rec[i + 1];
if(start.time <= t && endd.time > t)
{
return true;
}
else
{
return false;
}
}
int main(int argc, char *argv[]) {
scanf("%d%d", &N, &K);
for(int i = 0; i < N; i++)
{
char stat[5];
scanf("%s %d:%d:%d %s", rec[i].num, &rec[i].hh, &rec[i].mm, &rec[i].ss, stat);
if(!strcmp(stat, "in"))
{
rec[i].status = true;
}
if(!strcmp(stat, "out"))
{
rec[i].status = false;
}
rec[i].valid = false;//初始化全为false
rec[i].maxTime = 0;
rec[i].time = rec[i].hh * 3600 + rec[i].mm * 60 + rec[i].ss;
}
sort(rec, rec + N, cmpTime);
rec[0].id = 0;
for(int i = 1; i < N; i++)
{
if(!strcmp(rec[i].num, rec[i - 1].num))
{
rec[i].id = rec[i - 1].id;
}
else
{
rec[i].id = i;
}
}
//查找并标记有效记录
int in = 0, out = 0, next = 0, cnt = 0;
while(in < N)
{
next = in;
cnt = 0;
while(next < N && !strcmp(rec[in].num, rec[next].num))//车牌相同
{
if(cnt == 0 && rec[next].status == true)//找到第一个in
{
cnt = 1;
}
else if(cnt == 1 && rec[next].status == false)
{
cnt = 2;
}
next++;
}
if(cnt < 2)//说明没有有效记录
{
in = next;
continue;
}
while(in < next)
{
while(in < next - 1 && !(rec[in].status == true && rec[in + 1].status == false))
{
in++;
}
rec[in].valid = true;
out = in + 1;
rec[out].valid = true;
if(out == next)
{
in = next;
break;
}
in = out + 1;
}
}
//K次询问输入
while(K--)
{
int cntCars = 0;
int h, m, s, quesTime;
scanf("%d:%d:%d", &h, &m, &s);
quesTime = h * 3600 + m * 60 + s;
for(int i = 0; i < N; i++)
{
if(rec[i].valid)//是有效的 这辆车in的位置
{
if(rec[i].maxTime == 0 && rec[i].status)
{
cars[rec[i].id] += rec[i + 1].time - rec[i].time;
rec[i].maxTime = rec[i + 1].time - rec[i].time;
maxAns = max(maxAns, rec[i].maxTime);
}
if(judge(i, quesTime) && rec[i].status)
{
cntCars++;
i++;
}
}
}
printf("%d\n", cntCars);
}
for(int i = 0; i < N; i++)
{
if(cars[i] == maxAns)//此处有个小漏洞,下面会解释
{
printf("%s ", rec[i].num);
}
}
printf("%02d:%02d:%02d\n", maxAns / 3600, maxAns % 3600 / 60, maxAns % 60);
return 0;
}
其中发现了PAT这道题所有测试样例的一个漏洞,所有测试样例中没有全是累加获得的最长停留时间,总会有一个是连续时间内停车,然后做差得到的最大时间。
见代码最后一部分,maxAns是一次连续时间做差获得,而cars[]是进行累加的,如果所有车辆都是累加出来得到的最大时间(意思是,所有车辆一天至少进入了校园两次并且记录均有效),maxAns会小于cars[]中的所有数据,答案会出错。但PAT中并没有这样的测试样例,因此还有一丢丢漏洞。
使用map代码
#include <bits/stdc++.h>
using namespace std;
int N, K;
int maxAns = -1;
map<string, int> parkTime;
struct records{
char num[15];
int hh, mm, ss;
int time;//以秒为单位方便比较询问的时间点
bool status;//true:in;false:out
bool valid;//此条记录是否有效,true有效
records(){}
}rec[10005], validRec[10005];
bool cmpTime(records r1, records r2)//先按车牌排序,再按时间排序
{
if(strcmp(r1.num, r2.num))
{
return strcmp(r1.num, r2.num) < 0;
}
else if(r1.hh != r2.hh)
{
return r1.hh < r2.hh;
}
else if(r1.mm != r2.mm)
{
return r1.mm < r2.mm;
}
else
{
return r1.ss < r2.ss;
}
}
bool cmpByTime(records r1, records r2)
{
return r1.time < r2.time;
}
bool judge(int i, int t)//判断该车在这个时间点是否在校园内
{
records start = validRec[i];
records endd = validRec[i + 1];
if(start.time <= t && endd.time > t)//在校园内
{
return true;
}
else//不在校园内
{
return false;
}
}
int main(int argc, char *argv[]) {
scanf("%d%d", &N, &K);
for(int i = 0; i < N; i++)//输入及初始化
{
char stat[5];
scanf("%s %d:%d:%d %s", rec[i].num, &rec[i].hh, &rec[i].mm, &rec[i].ss, stat);
if(!strcmp(stat, "in"))
{
rec[i].status = true;
}
if(!strcmp(stat, "out"))
{
rec[i].status = false;
}
parkTime[rec[i].num] = 0;
rec[i].valid = false;//初始化全为false
rec[i].time = rec[i].hh * 3600 + rec[i].mm * 60 + rec[i].ss;
}
sort(rec, rec + N, cmpTime);
int index = 0;
for(int i = 0; i < N - 1; i++)
{
if(!strcmp(rec[i].num, rec[i + 1].num) && rec[i].status && !rec[i + 1].status)
{
validRec[index++] = rec[i];
validRec[index++] = rec[i + 1];
int inTime = rec[i + 1].time - rec[i].time;
parkTime[rec[i].num] += inTime;
maxAns = max(maxAns, parkTime[rec[i].num]);
}
}
//K次询问输入
sort(validRec, validRec + index, cmpByTime);
int now = 0, cntCars = 0;
bool isfir = false;
while(K--)
{
int h, m, s, quesTime;
scanf("%d:%d:%d", &h, &m, &s);
quesTime = h * 3600 + m * 60 + s;
while(now < index && validRec[now].time <= quesTime)
{
if(validRec[now].status)
{
cntCars++;
}
else
{
cntCars--;
}
now++;
}
printf("%d\n", cntCars);
isfir = true;
}
for(map<string, int>::iterator it = parkTime.begin(); it != parkTime.end(); it++)
{
if(it->second == maxAns)
{
printf("%s ", it->first.c_str());
}
}
printf("%02d:%02d:%02d\n", maxAns / 3600, maxAns % 3600 / 60, maxAns % 60);
return 0;
}