PAT日志 1095

顽强的小白

1095 Cars on Campus (30 分)

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 (≤10​4​​), the number of records, and K (≤8×10​4​​) 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

题目解析

给出校园内车辆进出记录,回答所给出时间校园内的停的车辆数,并且最后输出总计停留时间最长的车牌号。

属于时间排序问题,也就相应的有有效记录和无效记录。

  • 要如何区分有效记录,并且如何处理呢?
    之前做的一道题也有区分有效记录的过程(电话单的那一题),本题也是相同的道理,如果是有效的记录,必需满足,同一辆车的 in 和 out 挨着 ,因为后面需要访问这些记录,因此需要把所有的有效记录另存起来。

  • 如何进行时间查询,这里就很厉害了,我反正是没想出来,这是参考书的思路:首先,将所有有效记录单纯按照时间排序,遍历,(这里要说一点,题目所给的访问的时间是有时间顺序的,从早到晚,因此只用遍历一遍)设置一个下标 now 和当前车辆数 nowCar 当前记录为 in 车辆数加1,反之减1,直到询问的时间不再大于等于当前记录时间。

代码实现

const int maxk=80005;struct record{
 string name;
 int stastus;
 int hh,mm,ss,time;
}re[maxn],va[maxn];map <string,int> parkTime;bool cmp(record a,record b){
 if(a.name!=b.name){
  return a.name<b.name;
 }else{
  return a.time<b.time;
 }
}
bool cmp1(record a,record b){
 return a.time<b.time;
}
int maxTime=0; 
int main(){
 int n,k;
 string sta;
 scanf("%d%d",&n,&k);
 for(int i=0;i<n;++i){
  cin>>re[i].name;
  scanf("%d:%d:%d",&re[i].hh,&re[i].mm,&re[i].ss);
  re[i].time=re[i].hh*3600+re[i].mm*60+re[i].ss;
  cin>>sta;
  if(sta=="in") re[i].stastus=1;
  else re[i].stastus=0;
 }
 sort(re,re+n,cmp);
 int stay,num=0;
 for(int i=0;i<n-1;++i ){
  if(re[i].name==re[i+1].name&&re[i].stastus==1&&re[i+1].stastus==0){
    va[num++]=re[i];
    va[num++]=re[i+1];
    stay=re[i+1].time-re[i].time;
    if(parkTime.find(re[i].name)==parkTime.end()){
     parkTime[re[i].name]=0;
    }
    parkTime[re[i].name]+=stay;
    maxTime=max(parkTime[re[i].name],maxTime);
  }
 }
 sort(va,va+num,cmp1);
 int now=0,nowCar=0,q,hh,mm,ss;
 for(int i=0;i<k;++i){
  scanf("%d:%d:%d",&hh,&mm,&ss);
  q=hh*3600+mm*60+ss;
  while(now<num&&va[now].time<=q){
   if(va[now].stastus==1) nowCar++;
   else nowCar--;
   now++;
  }
  printf("%d\n",nowCar);
 }
 map<string,int>::iterator it;
 for(it=parkTime.begin();it!=parkTime.end();it++){
  if(it->second==maxTime){
   cout<<it->first<<" ";
  }
 }
 printf("%02d:%02d:%02d\n",maxTime/3600,maxTime%3600/60,maxTime%60);
 return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值