PAT A1095 Cars on Campus (30 分) 模拟 排序

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

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

       然后就是要考虑如何查询能够不超时。

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

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

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

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 mpCar;

int main()
{
    int N, K;
    cin >> N >> K;
    vector 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 vNames;
    for(map::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;
}


② Solution2:先筛选出所有的有效记录,之后将有效记录按照时间顺序排序,由于查询是按照时间增序进行的,所以只需要记录上一次查到了哪一条记录,以及上一次查询的时间还有多少辆车,在此基础上计算本次查询即可。

#include 

using namespace std;

int convertToSec(string &time)
{
    return stoi(time.substr(0,2)) * 3600 + stoi(time.substr(3,2)) * 60 + stoi(time.substr(6,2));
}

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

bool cmp(const record& a, const record& b)
{
    return a.time < b.time;
}

map mp;

int main()
{
    int N, K;
    cin >> N >> K;
    vector re, validRe;
    for (int i = 0; i < N; ++i)
    {
        string id, time, status;
        cin >> id >> time >> status;
        re.push_back(record(id, convertToSec(time), status[0] == 'i' ? 1 : 0));
    }
    sort(re.begin(), re.end());
    int maxTime = 0;
    vector maxTimeCars;
    for (int i = 1; i < N; ++i)
    {
        if(re[i].id == re[i-1].id && re[i].status == 0 && re[i-1].status == 1)
        {
            validRe.push_back(re[i-1]);
            validRe.push_back(re[i]);
            mp[re[i].id] += re[i].time - re[i-1].time;
            if(mp[re[i].id] > maxTime)
            {
                maxTime = mp[re[i].id];
                maxTimeCars.clear();
                maxTimeCars.push_back(re[i].id);
            }
            else if(mp[re[i].id] == maxTime)
            {
                maxTimeCars.push_back(re[i].id);
            }
        }
    }
    sort(validRe.begin(), validRe.end(), cmp);
    int lastNum = 0, lastIndex = 0;
    for (int i = 0; i < K; ++i)
    {
        string time;
        cin >> time;
        int t = convertToSec(time);
        int num = lastNum, index = lastIndex;
        while(index < validRe.size() && validRe[index].time <= t)
        {
            if(validRe[index].status == 1) num++;
            else num--;
            index++;
        }
        printf("%d\n", num);
        lastIndex = index;
        lastNum = num;
    }
    sort(maxTimeCars.begin(), maxTimeCars.end());
    for (int i = 0; i < maxTimeCars.size(); ++i)
    {
        printf("%s ", maxTimeCars[i].c_str());
    }
    printf("%02d:%02d:%02d", maxTime / 3600, maxTime %3600 / 60, maxTime % 60);
    return 0;
}

 

你可能感兴趣的:(PAT,Review)