PAT A1095 Cars on Campus (30 分) 排序

      题目大意:统计校园内某一时刻的车辆数。给出N条记录,每条记录包括 车牌、记录时间 和 状态(in/out)。然后给出K个时刻,查询每个时刻的总车辆数,这K个时刻是按照时间递增顺序给出的。与PAT A1016 Phone Bills相同,对于同一辆车而言,只有在时间上相邻且状态不同的两条记录被认为是有效的。与PAT A1016不同的是,本题数据量非常大,需要仔细优化。 

       核心问题还是有效记录的获取,这里由于时间只起到比较大小的作用,可以直接统一化成以秒为单位进行比较。然后对所有记录先按车牌排序,再按时间排序。满足同一车牌、时间相邻、状态不同的两条记录是有效的。

       然后就是要考虑如何查询能够不超时。我采取的办法是,设立一个以秒为单位的数组change[ ]记录每个时刻的车辆变化情况,大小是 23*3600+59*60+59,大约是87000。然后在记录 in / out 有效信息的同时,对change[ ]中的这两个位置的元素进行+1和-1的操作。这样,在没有车辆开入和开出的时刻,change中对应的位置仍然是0。然后开始查询,因为查询时间是递增的,所以可以利用上一次查询的结果,即 本次查询的结果 = 上次查询的结果 + [上次查询时间 + 1(s) ~ 本次查询时间] 的范围内 change的元素和。注意这里的范围是 上次查询时间+1s,否则会出现重复计算的问题。

      还有输出最大停留时间的车辆的信息,这里为了避免超时,不用先记录车辆信息再排序的方式, 而是在获取有效信息的同时,对 车辆的总停留时间 和 全部车辆的最大停留时间 也需要更新,最后只需要遍历map,获取停留时间是 最大停留时间 的车辆即可。

AC代码如下:

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstring>

using namespace std;

const int MAXN = 87000;
int change[MAXN] = {0};
int totalTime[10010] = {0};

struct record
{
    string name;
    int time;
    int status;
    record(string name, int time, int status)
    {
        this->name = name;
        this->time = time;
        this->status = status;
    }
    bool operator< (const record& another)
    {
        if(this->name != another.name) return this->name < another.name;
        else return this->time < another.time;
    }
};

map<string, int> mpCar;

int main()
{
    int N, K;
    cin >> N >> K;
    vector<record> v, validRecord;
    for (int i = 0; i < N; ++i)
    {
        char name[10], status[10];
        int h, m, s;
        scanf("%s %d:%d:%d %s", name, &h, &m, &s, status);
        v.push_back(record(string(name), h * 3600 + m * 60 + s, status[0] == 'i' ? 1 : -1));
    }
    sort(v.begin(), v.end());
    int i = 0;
    int maxTime = 0;
    while(i < v.size() - 1)
    {
        if(v[i].name == v[i+1].name && v[i].status == 1 && v[i+1].status == -1)
        {
            validRecord.push_back(v[i]);
            validRecord.push_back(v[i+1]);
            mpCar[v[i].name] += v[i+1].time - v[i].time;
            if(mpCar[v[i].name] > maxTime) maxTime = mpCar[v[i].name];
            change[v[i].time]++;
            change[v[i+1].time]--;
            i++;
        }
        i++;
    }

    int count = 0;
    int lastTime = 0;
    for (int query = 0; query < K; ++query)
    {
        int h, m, s;
        scanf("%d:%d:%d", &h, &m, &s);
        int time = h * 3600 + m * 60 + s;
        for (int j = lastTime; j <= time; ++j)
        {
            count += change[j];
        }
        printf("%d\n", count);
        lastTime = time + 1;
    }

    vector<string> vNames;
    for(map<string, int>::iterator it = mpCar.begin(); it != mpCar.end(); it++)
    {
        if(it->second == maxTime) vNames.push_back(it->first);
    }
    sort(v.begin(), v.end());
    for (int j = 0; j < vNames.size(); ++j)
    {
        printf("%s ", vNames[j].c_str());
    }
    printf("%02d:%02d:%02d", maxTime/3600, maxTime%3600/60, maxTime%3600%60);
    return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值