团体天梯练习 L2-042 老板的作息表

发布时间 2023-04-20 22:14:24作者: Amαdeus

L2-042 老板的作息表

新浪微博上有人发了某老板的作息时间表,表示其每天 \(4:30\) 就起床了。但立刻有眼尖的网友问:这时间表不完整啊,早上九点到下午一点干啥了?

本题就请你编写程序,检查任意一张时间表,找出其中没写出来的时间段。

输入格式:

输入第一行给出一个正整数 \(N\) ,为作息表上列出的时间段的个数。随后 \(N\) 行,每行给出一个时间段,格式为:

\(hh:mm:ss - hh:mm:ss\)

其中 \(hh\)\(mm\)\(ss\) 分别是两位数表示的小时、分钟、秒。第一个时间是开始时间,第二个是结束时间。题目保证所有时间都在一天之内(即从 \(00:00:00\)\(23:59:59\) );每个区间间隔至少 1 秒;并且任意两个给出的时间区间最多只在一个端点有重合,没有区间重叠的情况。

输出格式:

按照时间顺序列出时间表中没有出现的区间,每个区间占一行,格式与输入相同。题目保证至少存在一个区间需要输出。

输入样例:

8
13:00:00 - 18:00:00
00:00:00 - 01:00:05
08:00:00 - 09:00:00
07:10:59 - 08:00:00
01:00:05 - 04:30:00
06:30:00 - 07:10:58
05:30:00 - 06:30:00
18:00:00 - 19:00:00

输出样例:

04:30:00 - 05:30:00
07:10:58 - 07:10:59
09:00:00 - 13:00:00
19:00:00 - 23:59:59


解题思路

起初我自己的想法时,将开一个 \(24*60*60\) 的数组,用来记录每个时间点是否已经存在于这个时间表中,然后再使用双指针算法,如果当前左指针指向的时间点未被标记,那么说明此时间点不存在于时间表中,然后让右指针一直向右搜索,直到被标记也就是存在于时间表中的一个时间点,最后将左右指针此时停留在的时间区间作为一段不存在于时间表中的答案输出。这种方法比较繁琐,而且反而绕了弯路,最关键的是,最后没有拿到全分,因为没有样例,不太清楚是哪个地方出了问题。

正确且比较简单的做法是,将所有给出的时间段进行排序,然后所有出现断点的地方,都将这个时间段进行输出。不过需要将 {"", "\(00:00:00\)"} 和 {"\(23:59:59\)", ""}放入数组中一起进行排序,假如某个答案时间段是以 "\(00:00:00\)" 开始或者以 "\(23:59:59\)" 结束的,如果不预先将这两个时间点放入数组中,那么这个答案时间段会被遗漏。

/*   一切都是命运石之门的选择  El Psy Kongroo  */
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<functional>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<int, pii> piii;
typedef pair<double, double> pdd;
typedef pair<string, int> psi;
//typedef __int128 int128;
#define PI acos(-1.0)
#define x first
#define y second
//int dx[4] = {1, -1, 0, 0};
//int dy[4] = {0, 0, 1, -1};
const int inf = 0x3f3f3f3f, mod = 1e9 + 7;


int n;
typedef pair<string, string> pss;
vector<pss> t;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    cin >> n;
    while(n -- ){
        string a, s, b; cin >> a >> s >> b;
        t.push_back({a, b});
    }
    t.push_back({"", "00:00:00"});  //放入一天的起始时间
    t.push_back({"23:59:59", ""});  //放入一天的结束时间

    sort(t.begin(), t.end());  //排序 pair为双关键字排序

    for(int i = 0; i < (int)t.size() - 1; i ++ )
        if(t[i].y != t[i + 1].x)   //只输出时间出现断点的地方 即答案
            cout << t[i].y << " - " << t[i + 1].x << endl;

    return 0;
}