挤牛奶(acwing每日一题)

题目描述:

每天早上 55 点,三名农夫去牛场给奶牛们挤奶。

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

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

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

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

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

  1. 至少存在一名农夫正在挤奶的连续时间段的最长长度。
  2. 没有任何农夫在挤奶的连续时间段的最长长度。

注意:本题中给出的所有时间均为时刻(时间点),因此在本题中挤奶区间 [100,200][100,200] 和 [201,300][201,300] 中间会有长度为 11 秒的间歇时间。

输入格式:

第一行包含整数 N,表示农夫数量。

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

输出格式:

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

数据范围:

1≤N≤5000 ,0≤l≤r≤1e6;

输入样例:

3
300 1000
700 1200
1500 2100

输出样例:

900 300

分析步骤:

  第一:我们从输入的数据可以看出是分为一段一段的区间,由此我们可以去想到区间合并的知识点。

  第二:想到区间合并就只有三种情况 :1.两段互不相交;2.两段相交但是都有各自独有的;3.一段被包含在另一段之内;
            

  第三:用一个sort排序,只有这样你的左节点才会有规律,这样才可以去比较右节点

  第四:对于这道题,我们用个for循环从i==2开始(因为我们就可以避开区间左边界出界的问题) 我们可以将这三种情况用if来表达对于情况1(互相不相交)就存在可能是中断的时间,此时我们就用ans去收集这段时间并用max函数只取最大值,所以最长的中断时间答案就出来了情况2(相交但是有各自独有的)我们可以把此时第i个区间给扩大用第i个区间存下两个区间的全部的范围;情况3(一段被包含在另一段之内)我们可以用第i个区间也赋值成大的区间,因为我们只关注最长的挤奶时间,而不关注有几个最长的挤奶时间。

  第五:我们用一个for循环去看看那个区间的时间最长就记录下来。由此得出我们的最长挤奶时间 

代码输出:

#include <iostream>
#include <cstring>
#include <algorithm>
#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;
const int N = 5010;
int n ;
PII p[N],seg[N];

int main()
{
    cin>>n;
    int res = 0;
    int ans = 0;
    for (int i = 1; i <= n; i ++ ) cin >> seg[i].x >> seg[i].y;
    sort(seg + 1 , seg + n + 1);
    
    for(int i = 2 ; i <= n ; i ++){
        if(seg[i].x >= seg[i-1].x and seg[i].y <= seg[i-1].y){
           seg[i].x = seg[i-1].x , seg[i].y = seg[i-1].y;  
        }
        if(seg[i].x <= seg[i-1].y) seg[i].x = seg[i-1].x;
        if(seg[i].x > seg[i-1].y) ans = max(ans , seg[i].x - seg[i-1].y);
    }
    
    for(int i = 1 ; i <= n ; i ++){
        res = max(res , seg[i].y - seg[i].x);
    }
    cout<<res<<" "<<ans<<endl;
    return 0;
}

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值