老板的作息表[天梯赛]

文章介绍了如何使用C++编程实现区间合并算法,解决给定时间区间的问题,通过结构体、映射和vector等数据结构存储和处理时间,确保无遗漏地合并并输出有效区间。
摘要由CSDN通过智能技术生成

题目描述

在这里插入图片描述
在这里插入图片描述

输入样例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
输出样例1
04:30:00 - 05:30:00
07:10:58 - 07:10:59
09:00:00 - 13:00:00
19:00:00 - 23:59:59

输入样例2
1
13:00:00 - 18:00:00
输出样例2
00:00:00 - 13:00:00
18:00:00 - 23:59:59

思路

区间合并
1.存储结构:
①结构体Time,存储每一个时间端点具体的时分秒
②map,存储每一个时间端点和其转化为以秒为时间的映射
③vector存储用秒表示的一队给定时间区间
2.具体做法
①将存储结构中的数据存好之后,首先对vector数组进行排序,由于vector的元素是pair,使用sort,默认按pair的first由小到大排序
②初始化区间端点为负无穷,即没有区间,这样我们可以更新第一个区间
③判断从第二个开始的区间,如果当前区间的尾端点,比我们先前合并的区间首端点小,说明两个区间没有重合,则将先前的区间保存下来,并将新的区间端点,更新为当前我们判断的区间;否则,区间有重合,合并区间,更新尾端点

AC代码

#include <iostream>
#include <cstdio>
#include <vector> 
#include <map>
#include <algorithm>
using namespace std;
const int N = 100010;
typedef struct time
{
	int h, m, s; 
}Time;
typedef pair<int, int> PII; 
vector<PII> segs; //起始时间 终止时间 均以秒为单位 
map<int, Time> mp; //对应的以秒为单位的时间  具体时间 
Time t1, t2;

//void test()
//{
//	cout << "------" << endl; 
//	for(int i = 0; i < segs.size(); i ++)
//	{
//		int st = segs[i].first;
//		int ed = segs[i].second;
//		t1 = mp[st];
//		t2 = mp[ed];
//		printf("%02d:%02d:%02d - %02d:%02d:%02d\n", t1.h, t1.m, t1.s, t2.h, t2.m, t2.s);
//	}
//}

void merge()
{
	vector<PII> temp;
	int seg_st = -2e9, seg_ed = -2e9;
	for(int i = 0; i <segs.size(); i ++)
	{
		if(seg_ed < segs[i].first) //产生新的区间 
		{
			if(seg_st != -2e9) temp.push_back({seg_st, seg_ed});
			seg_st = segs[i].first;
			seg_ed = segs[i].second;
		}
		else seg_ed = max(seg_ed, segs[i].second); //有重合部分,合并区间 
	}
	if(seg_st != -2e9) temp.push_back({seg_st, seg_ed}); //不要忘记最后一个区间 
	segs = temp;
//	//测试区间合并正确性 
//	test();
	int st, ed;
	st = segs[0].first;
	t1 = mp[st];
	if(t1.h || t1.m || t1.s) printf("00:00:00 - %02d:%02d:%02d\n", t1.h, t1.m, t1.s); //判断从00:00:00到给定的最早时间是否有漏掉的时间 
	
	for(int i = 1; i < segs.size(); i ++) 
	{
		st = segs[i].first;
		ed = segs[i - 1].second;
		t2 = mp[st];
		t1 = mp[ed];
		printf("%02d:%02d:%02d - %02d:%02d:%02d\n", t1.h, t1.m, t1.s, t2.h, t2.m, t2.s);
	}
	
	//判断从给定的最晚时间到23:59:59是否有漏掉的时间  
	ed = segs[segs.size() - 1].second;
	t1 = mp[ed];
	if(t1.h != 23 || t1.m != 59 || t1.s != 59) printf("%02d:%02d:%02d - 23:59:59\n", t1.h, t1.m, t1.s);
}

int main()
{
	int n;
	scanf("%d", &n);
	for(int i = 0; i < n; i ++)
	{
		int h1, m1, s1, h2, m2, s2;
		scanf("%d:%d:%d - %d:%d:%d", &h1, &m1, &s1, &h2, &m2, &s2);
		t1 = {h1, m1, s1}; //存储当前区间的开始时间 
		t2 = {h2, m2, s2}; //存储当前区间的结束时间 
		int time1 = h1 * 3600 + m1 * 60 + s1; //开始时间转化为以秒为单位 
		int time2 = h2 * 3600 + m2 * 60 + s2; //结束时间转化为以秒为单位 
		mp[time1] = t1; //映射关系 
		mp[time2] = t2;
		segs.push_back({time1, time2});
	}
	sort(segs.begin(), segs.end());
	
//	//测试排序正确性 
//	test(); 
	
	merge();
	return 0;
} 

欢迎大家批评指正!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值