PAT 甲级 1095

 题目: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 (≤104), the number of records, and K (≤8×104) 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.

题目大意:给出n个车牌号、时间点、进出状态的记录,然后查询k个时间点这时校园内的车辆个数。最后还要输出在校园里面呆的时间最长的车的车牌号,以及呆了多久的时间。如果有多辆车就按照它的字母从小到大输出车牌。
配对要求是,如果一个车多次进入未出,取最后一个值;如果一个车多次out未进入,取第一个值
注意:一个车可能出入校园好多次,停车的时间应该取之和

//注意,这里是一天中呆的最久的时间,比如JH007BD,反复开入开出了两次,所以,它呆的时间要把两段时间都加上,而不是一段时间)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
struct Car
{
    char a[20]={0};
    int time=0;//以s为单位 进入/出去的时间
    int state=0;//0 代表出 1 代表进
}car[11000],temp[11000],value[11000];
bool cmp(Car a,Car b)
{
    return a.time<b.time;
};
map<string,int>mp;
map<string,int>mp1;
map<string,int>mp2;//用于做指针,判断in的合理性
map<string,int>::iterator it;
//注意逻辑问题,不要跳着思维,打好注释,特别是比较复杂的题目
int main()
{
    int n,k;
    cin>>n>>k;
    for(int i=0;i<n;i++)
    {
        int h,m,s,time;
        scanf("%s %02d:%02d:%02d",&car[i].a,&h,&m,&s);
        car[i].time=h*60*60+m*60+s;
        char a[5]={0};
        cin>>a;
        if(strcmp(a,"in")==0)//比较字符型数组
            car[i].state=1;
        else
            car[i].state=0;
    }
    sort(&car[0],&car[n],cmp);
    //处理数据,清除掉不合理的in和out,存入value中
    //mp2<车牌,value的下标>
    int j=0;
    for(int i=0;i<n;i++)
    {
        //判断该车是进是出,进就存入in,出就舍去
        if(car[i].state==1)//进
        {
            if(!mp1[car[i].a])//如果该车没有记录,或者为上一个状态为出的时候
            {
                mp2[car[i].a]=j;//记录该数据对应的value的下标,以便后续判断该in是否合理
                value[j++]=car[i];//记录该数据
                mp1[car[i].a]=1;//更新该数据的状态
            }
            else if(mp1[car[i].a]==1)
            {
                value[mp2[car[i].a]]=car[i];//剔除上一个入的数据,保留本次入的数据
            }
        }
        if(car[i].state==0)//出 上一个状态是入,则该出合理,上一个状态是出,则判断下一个数据
        {
            if(mp1[car[i].a]==1)
            {
                value[j++]=car[i];//记录该数据
                mp1[car[i].a]=0;//更新该数据的状态
            }
        }
    }
    int value_num=j;
    sort(&value[0],&value[value_num],cmp);
    //检查mp1的数据中是否全为0 ,把1去除
    for(it=mp1.begin();it!=mp1.end();it++)
    {
        if(it->second==1)
        {
            map<string,int>::iterator it1;
            //找到mp2中对应的value的下标,去除value中的该数据
            it1=mp2.find(it->first);
            value[it1->second].state=-1;//设置该车的状态为不存在,后续计算是直接去除
        }
    }
    int num=0;
    int j1=0;

    //一定要注意等号,如果查询的时间正好有车车进来了,那么该出也算哦,如果正好有车车出去了,那么该车车就不算了哦
    for(int i=0;i<k;i++)
    {

        int h,m,s,time,inquire;
        scanf("%02d:%02d:%02d",&h,&m,&s);
        inquire=h*60*60+m*60+s;
        //一定要注意等号,如果查询的时间正好有车车进来了,那么该出也算哦,如果正好有车车出去了,那么该车车就不算了哦
        //有可能同一时刻还有一辆进来,所以一定要查询
        for( j=j1;j<value_num&&value[j].time<=inquire;j++)
        {
            if(value[j].state==-1) continue;
            if(value[j].state==1) num++;
            if(value[j].state==0) num--;
        }
        j1=j;
        cout<<num<<endl;

    }
    sort(&value[0],&value[value_num],cmp);


    //输出最后一行数据
    mp1.clear();//中间变量,存放时间最长的车,以及对应的时间
    mp.clear();
    //计算数据为map</车牌,保留的时间>注意一辆车一天内进出两次,取总和

    for(int i=0;i<value_num;i++)
    {
        if (value[i].state == -1) { continue; }
        if (value[i].state == 1)
            mp[value[i].a] = value[i].time;
        else
        {
            int tt = value[i].time - mp[value[i].a];
            if(mp1[value[i].a])//如果有记录,说明该车已经登记过一次
            {
                    mp[value[i].a] = tt+mp1[value[i].a];
                    mp1[value[i].a] = mp[value[i].a];//与下一次out进行比较
            }
            else//没有记录的话那么直接保存该数据
            {
                mp[value[i].a] = tt;
                mp1[value[i].a] =tt;//与下一次out进行比较
            }
        }
    }
    mp1.clear();//中间变量,存放时间最长的车,以及对应的时间

    int max=0;
    for(it=mp.begin();it!=mp.end();it++)
    {

        if(it==mp.begin())
        {
            max=it->second;
            mp1[it->first]=it->second;
        }
        else
        {
            if(max==it->second)
            {
                mp1[it->first]=it->second;
            }
            else if(max<it->second)
            {
                mp1.clear();
                max=it->second;
                mp1[it->first]=it->second;
            }
        }

    }

    for(it=mp1.begin();it!=mp1.end();it++)
        cout<<it->first<<" ";
    int h,m,s;
    h=max/60/60;
    s=max%60;
    m=(max/60)%60;
    printf("%02d:%02d:%02d",h,m,s);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值