USACO_CHA1_挤牛奶

一、题目描述

链接https://www.acwing.com/problem/content/1345/
来源:ACwing

每天早上 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

二、题解

题目理解
有N名农夫挤牛奶,并且分别给了他么挤牛奶的开始时间和结束时间。要我们输出最长连续挤奶时间段最长无人挤奶连续时间段的长度。

解题思路
思路很清晰了,如果两个人的挤奶时间有重合部分,那么这两个人的挤奶时间就可以合并为一段。
当我们把所有能合并的时间都合并完后,最长连续挤奶时间段就是我们合并后区间段的最长长度;最长无人挤奶连续时间段就是我们合并后区间段间距离的最大值。

如何合并

区间合并问题:
1、将所有区间按照左端点排序
2、从左到右遍历所有区间,维护当前区间的合并区间

维护过程:
1、当前区间的左端点,在当下维护区间的r的左端,说明有交集。
   对当前区间的右端点和当前维护区间的右端点取较大值,
   作为当前维护区间的右端点。
2、当前区间的左端点在当下维护维护区间r的右端。
   说明当前区间和当前维护区间无交集。
   则当前维护区间结束,新的维护区间的[l,r]与当前区间相同。

时间复杂度:
O(nlogn),左端点排序的复杂度。

三、AC代码

#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 5010;
typedef struct
{
    int l;
    int r;
}Interval;
bool cmp(Interval x,Interval y)
{
    return x.l < y.l;
}
Interval Time[MAXN];
Interval inter[MAXN];
int n,num;
int main()
{
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> Time[i].l >> Time[i].r;
    }
    sort(Time,Time + n,cmp);

    inter[0].l = Time[0].l;
    inter[0].r = Time[0].r;
    for (int i = 1; i < n; i++)
    {
        if (Time[i].l <= inter[num].r)
        {
            // 当前区间可以和当前维护区间合并
            inter[num].r = max(inter[num].r,Time[i].r);
        }
        else
        {
            // 当前区间不能和当前维护区间合并
            inter[++num].l = Time[i].l;
            inter[num].r = Time[i].r;
        }
    }
    int ans1 = inter[0].r - inter[0].l;
    int ans2 = 0;
    for (int i = 1; i <= num; i++)
    {
        ans1 = max(ans1,inter[i].r - inter[i].l);
        ans2 = max(ans2,inter[i].l - inter[i-1].r);
    }
    cout << ans1 << " " << ans2 << endl;
    system("pause");
    return 0;
}

如果该题解对您有帮助,还望您不吝点赞。
欢迎讨论交流,期待共同进步!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值