PAT_A1095
PAT甲级1095.
目录
A1095
题目
样例
输入:
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
思路和坑点
主要的难点在于:筛选有效信息,大规模数据的快速排序,查询的思路。
筛选有效信息时,将所有信息按照先车牌号,再时间的顺序,然后寻找到一组同一车辆的对应信息作为一组有效记录。
大规模的数据排序,尤其是结构体,建议使用下标的方式排序。
查询的时候按照是时间顺序排序,然后在查询时间点之前的所以记录进行统计,进入则数量加一,出去则数量减一,由于是按照时间先后顺序进行线性查询,所以一次遍历即可,注意遍历指针的定义和初始化要在循环外。
AC代码
#include<bits/stdc++.h>
using namespace std;
#define time_int(hh,mm,ss) (hh*3600+mm*60+ss) //将时间转化为整形,定义成宏,速度更快些
typedef struct node{
string id; //车牌号
int time,tag=1; //时间和进出标记,默认1为进,0为出
}Car;
int cmptag=1; //排序标记
vector<Car> all; //所有数据
vector<int> sid,valid; //sid用于第一次下标排序,valid用于保存有效信息的下标,并用于第二次的下标排序
map<string,int> parktime; //记录每个车的停车时间
bool cmp(int a,int b){ //比较函数
if(cmptag==1){ //第一次排序,先按照车牌号排,再按照时间先后排
if(all[a].id!=all[b].id) return all[a].id<all[b].id;
else return all[a].time<all[b].time;
}
else{
return all[a].time<all[b].time; //第二次只按照时间排序
}
}
int main(void){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt","r",stdin);
#endif
int n,k,hh,mm,ss,maxtime=-1; //初始化参数,maxtime表示停留的最长时间
scanf("%d%d",&n,&k);
all.resize(n); sid.resize(n); //初始化容器大小
for(int i=0;i<n;i++){
sid[i]=i; //初始化下标排序数组的下标
cin>>all[i].id; //读入信息
char temp[4];
scanf("%d:%d:%d %s",&hh,&mm,&ss,temp);
all[i].time=time_int(hh,mm,ss);
if(temp[0]=='o') all[i].tag=0; //如果是出,tag标记为0
}
sort(sid.begin(),sid.end(),cmp); //第一次排序
for(int i=0;i<n-1;i++){ //删选有效信息
int a=sid[i],b=sid[i+1]; //从排好序的序列中,取出相邻的两条信息
if(all[a].id==all[b].id&&all[a].tag==1&&all[b].tag==0){ //如果这两条是同一辆车,且前一个为进,后一个为出,表示一对有效信心
valid.push_back(a); valid.push_back(b); //记录有效记录的下标
int intime=all[b].time-all[a].time; //计算停车时间
parktime[all[a].id]+=intime; //总停车时间累加
maxtime=max(maxtime,parktime[all[a].id]);//更新最大停车时间
}
}
cmptag=0; //修改排序标记,对有效记录,进行第二次排序
sort(valid.begin(),valid.end(),cmp);
int j=0,numcnt=0; //j用于遍历有效记录,numcnt用于记录当前车辆个数
for(int i=0;i<k;i++){
scanf("%d:%d:%d",&hh,&mm,&ss); //读入查询信息
int qtime=time_int(hh,mm,ss);
for(j;j<valid.size();j++){ //遍历有效信息,因为查询是按照时间顺序的,因此只需要遍历一遍
int ind=valid[j]; //取出一条有效记录的下标
if(all[ind].time>qtime) break; //如果该记录在查询事件之后,则本次查询结束
if(all[ind].tag==1) numcnt++; //如果是进入,numcnt加一
else numcnt--; //如果是出去,numcnt减一
}
printf("%d\n",numcnt); //输出本次查询结果
}
for(auto it=parktime.begin();it!=parktime.end();it++){
if(it->second==maxtime) //遍历停车时间的容器,并输出和maxparktime相等的车辆id
printf("%s ",it->first.c_str()); //map自身有序,保证了id的有序
}
printf("%02d:%02d:%02d",maxtime/3600,maxtime%3600/60,maxtime%60);
return 0;
}