【AcWing】蓝桥杯集训每日一题Day9|区间合并|1343.挤牛奶(C++)

1343.挤牛奶
1343. 挤牛奶 - AcWing题库
难度:简单
时/空限制:1s / 64MB
总通过数:4627
总尝试数:13242
来源:
usaco training 1.3
算法标签区间合并差分

题目内容

每天早上 5 点,三名农夫去牛场给奶牛们挤奶。
现在从 5 点开始按秒计时,第一名农夫在第 300 秒开始给牛挤奶,并在第 1000 秒停止挤奶。
第二名农夫在第 700 秒开始给牛挤奶,并在第 1200 秒停止挤奶。
第三名农夫在第 1500 秒开始给牛挤奶,并在第 2100 秒停止挤奶。
从开始挤奶到挤奶完全结束,这一期间,至少存在一名农夫正在挤奶的连续时间段的长度最长为 900 秒(第 300 秒至第 1200 秒),完全没有任何农夫在挤奶的连续时间段的长度最长为 300 秒(第 1200 秒至第 1500 秒)

现在给你 N 名农夫挤 N 头奶牛的工作时间表,请你求出:

  1. 至少存在一名农夫正在挤奶的连续时间段的最长长度。
  2. 没有任何农夫在挤奶的连续时间段的最长长度。
    注意:本题中给出的所有时间均为时刻(时间点),因此在本题中挤奶区间 [100,200][201,300] 中间会有长度为 1 秒的间歇时间。
输入格式

第一行包含整数 N,表示农夫数量。
接下来 N 行,每行包含两个非负整数 l,r,表示农夫挤奶的开始时刻和结束时刻。

输出格式

共一行,包含两个整数,分别表示最长连续挤奶时间以及最长连续无人挤奶时间。

数据范围

1≤N≤5000,
0≤l≤r≤10^6

输入样例:
3
300 1000
700 1200
1500 2100
输出样例:
900 300
题目详解

给出的不是时间而是时刻

求出至少有一名农夫正在挤奶的连续时间段的最大长度
就是求这些区间的并集
按题中的例子
第一个区间是900,第二个区间是600
第一问的答案就是900
![[Pasted image 20240330191918.png]]

没有任何农夫在挤奶的连续时间段的最长长度
合并完所有区间以后,找到最左边一个端点和最右边一个端点,看一下中间间隔的最大距离
例子里只有一个间隔300
所以第二问的答案是300

给若干个区间,把所有区间合并一下,找一下合并之后区间的最大长度,和合并之后所有区间中间的最大空缺的长度

N的范围是5000,时间复杂度控制在 O ( n 2 ) O(n^2) O(n2)以内就可以

合并区间有一个模板算法
803.区间合并

代码
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

#define x first
#define y second

typedef pair<int, int> PII;

const int N = 5010;

//定义区间长度
int n;
//定义区间的数组
PII segs[N];

int main()
{
	//读入所有区间个数
	scanf("%d", &n);
	//读入所有区间
	for (int i = 0; i < n; i ++)
		scanf("%d%d", &segs[i].x, &segs[i].y);
	//将所有区间排序
	sort(segs, segs + n);

	int res1 = 0, res2 = 0;
	//区间合并的模板
	//l,r先指向第一个区间
	int l = segs[0].x, r = segs[0].y;
	//枚举一下所有的区间,从第二个开始
	for (int i = 1; i < n; i ++)
	{
		//当前区间的左端点小于等于r的话,就更新一下r
		if (segs[i].x <= r)
			r = max(r, segs[i].y);
		//否则表示找到了一个区间
		else
		{
			//先更新一下第一问的长度
			res1 = max(res1, r - l);
			//再更新一下第二问的长度
			res2 = max(res2, segs[i].x - r);
			//更新一下当前维护的区间
			l = segs[i].x, r = segs[i].y;
		}
	}
	//更新一下最后维护的区间
	res1 = max(res1, r - l);
	printf("%d %d\n", res1, res2);

	return 0;
}
  • 17
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值