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.
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.
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.
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
1
4
5
2
1
0
1
JH007BD ZD00001 07:20:09
这题没有完全AC哈,只拿了27分,打算先放一会不做了(从昨天下午做到了今天中午,修修补补,还是错了一个测试点【4】)。代码都写了注释,没事干的同学可以看一看,虽然并不是正确答案……~
等过几天改了之后完全AC了再修改叭(逃)
【2020.05.07 13:13】我终于过了T T,原来是我的时间函数计算有问题(这也能AC五个测试点??我是没想到的),原因在于计算两个时间相加的时候:h_result = h_a+h_b;
,这里写赋值号的话,那么如果分
上有进位,就不会进到时
上面去,因此,应该改成h_result += h_a+h_b;
,这样的话,就算有进位也没事,因为是累加上去的,而不是赋值(赋值的话会覆盖掉之前进位累加上去的1)。
这里说一下这题的大意:
这题的想法还是很简单的,但是要处理的东西很多,很繁琐,所以就要花一点时间(我写了一个晚上+一个上午+一个中午……),首先,需要把题目给出的所有信息读入,然后对这些信息排个序,优先车牌字母序,其次是时间,这样的话,排完就能做到一个车牌号对应一块内容,每一块内容呢,又是按时间升序排序的~
然后就是筛选有用信息,因为题目说了,需要in和out配对才能算一组有效信息,因此,只有当当前的i和下一个i+1的车牌号相同,且当前的i的状态是in,以及i+1的状态是out时,这两组才能算作有效信息,于是放入Valid数组里(存放筛选后的有效信息,我这里一开始是把无效信息直接删了,后来发现这是不对的,虽然我也不知道哪儿不对……但就是错了一个测试点,分成两个数组分开放马上就AC了一个测试点……),同时,计算当前车牌号对应的停留时间长度(这里最好用map,这样的话string就正好映射一个时间)。
然后再对Valid数组按时间升序排列,这样就能得到一天中,从早到晚,汽车进出校园的时刻表了。于是,遍历Valid数组,计算当前时刻校园内的汽车数量(我这里还是用了一个map,不同于上一个的是,这里是时间映射汽车数量,因为时间我是用hh:mm:ss的方式表示的,所以是string->int)。计算汽车数量的方式很简单,只要碰到in,就cnt++,然后把它放入自己设置的map里,碰到out,就cnt–,然后再把它放入自己写的map里。
最后就是查询啦,这里的话要提一点,最好计算汽车数量和查询分开来做,先把每个时刻的汽车数量预处理好,再去对每个查询的时刻进行计算,否则会出现一些小问题(我一开始就是一边计算汽车数量,一边判断查询的时刻,后来发现这么做的话,如果时刻表里的相邻两条时刻之间有多次查询的话,那么我这么算是错的)。另外,因为查询的时刻也是按升序排列的,所以最好把迭代器it放在循环最外面,这样的话就不用每次从头开始遍历map了(如果每次从头开始遍历map,肯定会超时)。
查询的时候要处理三个问题:
至于怎么找到停留最长时间和对应的车牌号就很简单啦,这里就不多说了,具体看代码叭~
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
struct car{
string plate_number, time, status;
car(){
plate_number.clear();
time = "00:00:00";
status.clear();
}
};
struct info{
string TimeofDuration;
info(){
TimeofDuration = "00:00:00";
}
};
vector<car> List, Valid;//List用来存放原始数据,Valid用来存放有效数据
vector<string> LongestCars;//存放停留最长时间的车牌号
map<string, info> CarsInfo;//每个车牌号对应自己的停留总时间
map<string, int> num;//每个时刻对应的汽车数量
string addTime(string a, string b){//求时间a+时间b的和
string result;
int h_a = stoi(a.substr(0,2));
int m_a = stoi(a.substr(3,2));
int s_a = stoi(a.substr(6,2));
int h_b = stoi(b.substr(0,2));
int m_b = stoi(b.substr(3,2));
int s_b = stoi(b.substr(6,2));
int h_result = 0, m_result = 0, s_result = 0;
if(s_a+s_b>=60){
s_result = s_a+s_b-60;
m_result += 1;
}
else s_result = s_a + s_b;
if(m_a+m_b>=60){
m_result += m_a+m_b-60;
h_result += 1;
}
else m_result += m_a+m_b;
h_result = h_a+h_b;
string hh = to_string(h_result);
string mm = to_string(m_result);
string ss = to_string(s_result);
while(hh.length()<2){
hh.insert(0, "0");
}
while(mm.length()<2){
mm.insert(0, "0");
}
while(ss.length()<2){
ss.insert(0, "0");
}
result = hh+":"+mm+":"+ss;
return result;
}
string calculateTime(string s, string e){//求e-s的时间差
string result;
int h_s = stoi(s.substr(0,2));
int m_s = stoi(s.substr(3,2));
int s_s = stoi(s.substr(6,2));
int h_e = stoi(e.substr(0,2));
int m_e = stoi(e.substr(3,2));
int s_e = stoi(e.substr(6,2));
int h_result = 0, m_result = 0, s_result = 0;
if(s_e-s_s<0){
s_e += 60;
m_e -= 1;
s_result = s_e - s_s;
}
else s_result = s_e - s_s;
if(m_e-m_s<0){
m_e += 60;
h_e -= 1;
m_result = m_e - m_s;
}
else m_result = m_e - m_s;
h_result = h_e - h_s;
string hh = to_string(h_result);
string mm = to_string(m_result);
string ss = to_string(s_result);
while(hh.length()<2){
hh.insert(0, "0");
}
while(mm.length()<2){
mm.insert(0, "0");
}
while(ss.length()<2){
ss.insert(0, "0");
}
result = hh+":"+mm+":"+ss;
return result;
}
bool cmp2(car a, car b){//按时间排序
return a.time<b.time;
}
bool cmp(car a, car b){
if(a.plate_number!=b.plate_number) return a.plate_number<b.plate_number;
else return a.time<b.time;
}
int main()
{
int N, K;
cin>>N>>K;
for(int i=0;i<N;i++){
string tmpNumber, tmpTime, tmpStatus;
car tmp;
cin>>tmpNumber>>tmpTime>>tmpStatus;
tmp.plate_number = tmpNumber;
tmp.time = tmpTime;
tmp.status = tmpStatus;
List.push_back(tmp);
}
sort(List.begin(), List.end(), cmp);//对原始数据进行排序,优先车牌号字典序,其次是时间
for(int i=0;i<List.size();i++){
if(i+1<List.size()&&List[i].status=="in"&&List[i+1].status=="out"&&List[i].plate_number==List[i+1].plate_number){
//寻找有效数据:当前i和i+1为同一个车牌号,且i的状态是in,i+1的状态是out
Valid.push_back(List[i]);
Valid.push_back(List[i+1]);
string tmpDuration = calculateTime(List[i].time, List[i+1].time);
CarsInfo[List[i].plate_number].TimeofDuration = addTime(CarsInfo[List[i].plate_number].TimeofDuration, tmpDuration);
}
}
sort(Valid.begin(), Valid.end(), cmp2);//对Valid数组进行时间排序
int cnt = 0;
for(int i=0;i<Valid.size();i++){
if(Valid[i].status=="in"){
cnt++;
num[Valid[i].time] = cnt;//放入当前时刻汽车的数量
}
else{
cnt--;
num[Valid[i].time] = cnt;
}
}
map<string, int>::iterator it = num.begin();
for(int i=0;i<K;i++){
string tmpname;
cin>>tmpname;
bool flag = false;
while(it!=num.end()){
if(it->first>tmpname&&it==num.begin()){//如果查询的时刻是最早的
flag = true;
cout<<0<<'\n';//说明此时一辆车也没有
break;
}
else if(it->first>tmpname&&it!=num.begin()){//如果查询的时刻比it指向的时刻要小
flag = true;
it--;//应该取it的前一个的值
cout<<it->second<<'\n';
break;
}
else if(it->first==tmpname){//如果恰好等于此时it指向的时刻
flag = true;
cout<<it->second<<'\n';//那么直接输出
break;
}
it++;
}
if(flag==false){//如果查询的时刻是最大的
it--;//此时it应该指向了num.end(),因此要回退一位,指向最后一个元素
cout<<it->second<<'\n';//输出最后的汽车数量
}
}
string longestTime = "00:00:00";
for(map<string, info>::iterator it = CarsInfo.begin();it!=CarsInfo.end();it++){
if(it->second.TimeofDuration>longestTime){//更新最长时间
longestTime = it->second.TimeofDuration;
}
}
for(map<string, info>::iterator it = CarsInfo.begin();it!=CarsInfo.end();it++){
if(it->second.TimeofDuration==longestTime){//寻找停留最长时间的车子
LongestCars.push_back(it->first);
}
}
sort(LongestCars.begin(), LongestCars.end());//对车牌号进行升序排列
for(int i=0;i<LongestCars.size();i++){//依次输出
if(i==0) cout<<LongestCars[i];
else cout<<" "<<LongestCars[i];
}
cout<<" "<<longestTime;
return 0;
}