题目大意:
给出N条记录,每条记录给出一辆车的车牌号、当前时刻以及出入校情况(入校(in)还是出校out))。然后给出K个查询,每个查询给出一个时刻,输出在这个时刻校园内的车辆数。查询完毕后输出在学校内停留时间最长的车辆的车牌号(如果有多个,就一并输出)和
对应的停留时间。
算法思路:
该题和1016 Phone Bills的数据处理要求很相似, 这里要求给定某一个时刻,要求当前时刻有多少辆车在停车场,最直观的想法就是用一个变量(car_num)来记录车辆数目,从开始时刻到查询时刻,遇到in的记录就加一,遇到out的时候就减一,然后就得到当前查询时刻有多少车辆存在停车场了,但是该使用方法有一个前提条件,那就是所有的记录都得是有效记录,但是这里的记录有可能是无效的,所以,第一件事就是将记录所有的有效记录全部筛选出来存放在valid_records数组中,然后对于对于每一次查询就可以按照上述方法获得车辆数目,对于最长的停车时间长度可以在筛选有效记录的时候记录最长的停车时间和对应的车牌号码。
排序规则1:
首先按照车牌号分组,按照字典序排序,对于车牌号相同的按照时间先后排序,这是为了筛选有效记录。
排序规则2:
按照时间先后排序。
筛选有效记录的方法:
先按照排序规则一进行排序,使用指针i遍历所有的记录,这里的i最大为N-2,因为有效记录为一对,所以i<N-1即可。首先得判断i和i+1条记录为同一辆车的记录,否则无意义,然后再判断i和i+1的status分别为in和out,这样的记录才是一对有效记录,对于每一条有效记录,我们将i和i+1添加进valid_records数组中,然后再累计该车辆的停车时间,这里使用map<string,int> cars进行存储每一辆车对应的累计停车时间,
最后在记录最大的停车时长即可(用max_parking_time记录)
获取查询时刻停车场的车辆数目的方法:
先按照排序规则2排序,然后我们注意到查询的时刻是依次递增的,也就是说,如果每一次查询都是从都开始查询的话,会和上一次查询的记录重复,可以采取紧接着上一次查询位置往后查询车辆进出情况的方法,我们使用index记录上一次查询的记录位置,初始为0,使用car_num记录上一次查询停车场车辆的停留数目,只要当前index指向的记录的时间<=查询时间,那么就重复以下操作:
1、如果index指向记录的status为in,car_num++;
2、如果index指向记录的status为out,car_num--;
注意:
1、对同一辆车来说,配对的on和off必须满足在把这辆车的记录按时间顺序排列后,在它们之间不允许出现其他on或者off的记录;否则,将被视为无效记录。
2、如果每一次查询都是从00:00:00开始查询的话,会超时。
3、有可能查询时间在所有记录时刻之后,比如查询为23:59:59,但是记录的最靠后的时间为20:00:00,那么index得判断是否valid_records遍历完毕了。测试点1和2考察该点(自己测试得到的结果,不一定准确)
提交结果:
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include<map>
using namespace std;
struct Record{
string plate_number ;//车牌号码
int time;
bool status;// in为true,out为false
};
int getSeconds(int hh,int mm,int ss){
return hh*3600+mm*60+ss;
}
bool cmp(Record a,Record b){
if(a.plate_number!=b.plate_number){
return a.plate_number<b.plate_number;
}else{
return a.time<b.time;
}
}
bool cmpByTime(Record a,Record b){
return a.time<b.time;
}
int main(){
int N,K;//记录总数和查询总数
scanf("%d %d",&N,&K);
vector<Record> records;
Record record;
char plate_number[20];
int hh,mm,ss;
char status[10];
for(int i=0;i<N;++i){
scanf("%s %d:%d:%d %s",plate_number,&hh,&mm,&ss,status);
record.plate_number = plate_number;
record.time = getSeconds(hh,mm,ss);
record.status = strcmp(status,"in")==0;
records.push_back(record);
}
sort(records.begin(),records.end(),cmp);
//筛选无效记录
map<string,int> cars;//每一辆车停车的最长时间
int max_parking_time = -1;//最长停车时间
vector<Record> valid_records;
int begin=0,next=0;
for(int i=0;i<N-1;++i){
if(records[i].plate_number==records[i+1].plate_number){
// i和i+1是同一辆车
if(records[i].status&&!records[i+1].status){
//i为in,i+1为out,i与i+1为一对有效记录
valid_records.push_back(records[i]);
valid_records.push_back(records[i+1]);
int parking_time = records[i+1].time-records[i].time;//停车时间
// 更新该辆车的累计停车时间
cars[records[i].plate_number] += parking_time;
max_parking_time = max_parking_time<cars[records[i].plate_number]?cars[records[i].plate_number]:max_parking_time;//更新所有车辆最长停车时间
}
}
}
//根据时间进行排序
sort(valid_records.begin(),valid_records.end(),cmpByTime);
//查询开始
int index = 0;//当前查询记录的下标
int car_num = 0;//当前停车场的车辆数目
for(int i=0;i<K;++i){
scanf("%d:%d:%d",&hh,&mm,&ss);
int query_time = getSeconds(hh,mm,ss);
// 从index一直找到停车时间大于query_time的前面一辆记录即可
while(index<valid_records.size()&&valid_records[index].time<=query_time){
if(valid_records[index].status){
++car_num;
}else{
--car_num;
}
++index;
}
printf("%d\n",car_num);
}
//输出最长停车时间的车牌号和时间
map<string,int>::iterator it;
for(it=cars.begin();it!=cars.end();++it){
if(it->second==max_parking_time){
printf("%s ",it->first.c_str());
}
}
printf("%02d:%02d:%02d",max_parking_time/3600,max_parking_time%3600/60,max_parking_time%60);
return 0;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。