usaco training-挤牛奶

文章描述了一个关于农夫挤奶时间安排的问题,通过区间合并算法来找出最长的连续挤奶时间和最长的连续无人挤奶时间。输入包含农夫的挤奶起止时刻,经过排序后,逐个处理区间以找到最大值。输出为这两个最长时间段的长度。
摘要由CSDN通过智能技术生成


8


4
题目描述
每天早上 5 点,三名农夫去牛场给奶牛们挤奶。

现在从 5 点开始按秒计时,第一名农夫在第 300 秒开始给牛挤奶,并在第 1000 秒停止挤奶。

第二名农夫在第 700 秒开始给牛挤奶,并在第 1200 秒停止挤奶。

第三名农夫在第 1500 秒开始给牛挤奶,并在第 2100 秒停止挤奶。

从开始挤奶到挤奶完全结束,这一期间,至少存在一名农夫正在挤奶的连续时间段的长度最长为 900 秒(第 300 秒至第 1200 秒),完全没有任何农夫在挤奶的连续时间段的长度最长为 300 秒(第 1200 秒至第 1500 秒)。

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

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

输入格式
第一行包含整数 N,表示农夫数量。

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

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

数据范围
1≤N≤5000,
1≤l≤r≤106
输入样例:
3
300 1000
700 1200
1500 2100
输出样例:
900 300
算法:
本题是经典的区间合并问题,803. 区间合并可以作为先导题。
1. 将每个农夫的工作区间按开始时间排序,处理就变得容易了。开始时间具备单调性后,区间之间的关系只有以下三种状态(不包含相等的情况):

状态1: |----------|
        l       r
                        |-----|
                seg[i].first

状态2:|----------|
        l       r
            |----------|
    seg[i].first    seg[i].second

状态3:|----------|
        l       r
            |--|
seg[i].first    seg[i].second

1. 状态2、状态3为seg[i].first <= r的情况,这时需判断seg[i].second与r的大小关系。若是状态2,则需及时更新r的值。
2. 状态1表示已遇到新的无人区间,这时需更新最长连续工作时间和最长无人工作时间,然后更新l为seg[i].first,r为seg[i].second开始新的搜索。

#include<bits/stdc++.h>
using namespace std;
#define f first
#define se second
int n,ans,ans2;
pair<int,int> a[5001];
int main(){
	cin>>n;
	for(int i=0;i<n;i++){
		scanf("%d%d",&a[i].f,&a[i].se);
	}
	sort(a,a+n);
	int l=a[0].f,r=a[0].se;
	for(int i=1;i<n;i++){
		if(a[i].f<=r){
			r=max(r,a[i].se);
		}else{
			ans=max(ans,r-l);
			ans2=max(ans2,a[i].f-r);
			l=a[i].f,r=a[i].se;
		}
	}
	ans=max(ans,r-l);
	cout<<ans<<" "<<ans2;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值