题目大意:统计校园内某一时刻的车辆数。给出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
② 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;
}