U S A C O 1.2 挤 牛 奶 USACO\ 1.2\ 挤牛奶 USACO 1.2 挤牛奶
题目链接:SSL 1088
题目
三个农民每天清晨 5 5 5点起床,然后去牛棚给 3 3 3头牛挤奶。第一个农民在 300 300 300时刻(从 5 5 5点开始计时,秒为单位)给他的牛挤奶,一直到 1000 1000 1000时刻。第二个农民在 700 700 700时刻开始,在 1200 1200 1200时刻结束。第三个农民在 1500 1500 1500时刻开始 2100 2100 2100时刻结束。期间最长的至少有一个农民在挤奶的连续时间为 900 900 900秒(从 300 300 300时刻到 1200 1200 1200时刻),而最长的无人挤奶的连续时间(从挤奶开始一直到挤奶结束)为 300 300 300秒(从 1200 1200 1200时刻到 1500 1500 1500时刻)。
你的任务是编一个程序,读入一个有 N N N个农民 ( 1 < = N < = 5000 ) (1 <= N <= 5000) (1<=N<=5000)挤 N N N头牛的工作时间列表,计算以下两点(均以秒为单位):
- 最长至少有一人在挤奶的时间段。
- 最长的无人挤奶的时间段。
输入
第一行:一个整数
N
N
N。
第二行~第
N
+
1
N+1
N+1行:每行两个小于
1000000
1000000
1000000的非负整数,表示一个农民的开始时刻与结束时刻。
输出
一行,两个整数,即题目所要求的两个答案。
样例输入
3
300 1000
700 1200
1500 2100
样例输出
900 300
思路
这道题用离散化来做。
离散化之后,我们枚举每一个时间区间。
如果有人工作,我们就把这个工作的时间加入到连续工作时间,并把连续工作时间和最大连续工作时间比较,取最大值。
如果没有人工作,就把连续工作时间清零,且与最长无人挤奶时间比较,取最大值。
最后,我们只要输出最大连续工作时间和最长无人挤奶时间,就可以了。
代码
#include<cstdio>
#include<algorithm>
#define ll long long
#define max(x, y) (x) > (y) ? (x) : (y)
using namespace std;
ll n, a[3][5001], b[10001], k, ans, ans1, ans2;
int main() {
scanf("%lld", &n);//读入
for (ll i = 1; i <= n; i++) {
scanf("%lld %lld", &a[1][i], &a[2][i]);//读入
b[++k] = a[1][i];//标记
b[++k] = a[2][i];
}
sort(b + 1, b + k + 1);//离散化
for (ll i = 2; i <= k; i++) {
bool yes=0;//初始化
for (ll j = 1; j <= n; j++)//枚举每一个人
if (b[i] > a[1][j] && b[i] <= a[2][j]) {//判断是否在工作
ans += b[i] - b[i - 1];//更新连续工作时间
ans1 = max(ans1, ans);//求出最大值
yes = 1;//标记
break;//找到了就退出
}
if (!yes) {//没有工作
ans2 = max(ans2, b[i] - b[i - 1]);//求出最长的无人挤奶时间
ans = 0;//连续工作时间清零
}
}
printf("%lld %lld", ans1, ans2);//输出
return 0;
}