1 条题解
-
0
自动搬运
来自洛谷,原作者为

学而思李老师
ด้้้้้็้้้็็็็็้้้้้็็็็็้้้้้้็็็็็้้้้้็็็็็้้้้้้็็็็็้้้้้็็็็็้้้้้้็็็็็้้้้้็็็็็้้้้้้็็搬运于
2025-08-24 21:22:24,当前版本为作者最后更新于2019-08-05 15:27:58,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
P1204 [USACO1.2]挤牛奶Mixing Cows
又是一道模拟
水题。方法1:布尔数组,打标记,输出
在我的CF440A的题解里面,已经详细讲过关于布尔数组打标记的方法了。这道题目中,我们也可以用这种方法,把每一个时刻是否有人挤奶标记出来,最后用循环找到最长有人挤奶的时间和最长无人挤奶的时间。特别注意:300~900其实是601秒,题目中只有600秒。算的时候,一定从300标记到899才不会出错。
对于这种方法,我花了一个图来表示:

code:
#include <cstdio> #include <cstring> using namespace std; bool timeline[1000005]; int my_max(int x, int y){ return x > y ? x : y; } int my_min(int x, int y){ return x < y ? x : y; } int main(){ memset(timeline, false, sizeof(timeline)); int n, tmpx, tmpy, maxz = -1, maxa = -1; scanf("%d", &n); for(int i = 1; i <= n; i ++){ scanf("%d%d", &tmpx, &tmpy); for(int i = tmpx; i < tmpy; i ++){ timeline[i] = true; } maxz = my_max(maxz, tmpy); maxa = my_min(maxa, tmpx); } int maxx = -1, maxy = -1; int tmpa = 0, tmpb = 0; for(int i = maxa; i <= maxz; i ++){ if(timeline[i]){ tmpa ++; tmpb = 0; } else{ tmpa = 0; if(i < maxz){ tmpb ++; } } maxx = my_max(maxx, tmpa); maxy = my_max(maxy, tmpb); } printf("%d %d", maxx, maxy); return 0; }方法2:结构体sort
上面的方法虽然稳定而简单,但是如果数据狠一些就会超时。所以,我们可以不用暴力的方法,使用减法可以算出挤奶时间和未挤奶时间。所以,代码如下(思路看注释)
#include <cstdio> using namespace std; int my_max(int x, int y){ return x > y ? x : y; //取最大值函数,<algorithm>里面的太慢了 } int main(){ int o; scanf("%d", &o); int maxx = -1, maxy = -1, lasttmp = 0; for(int i = 1; i <= o; i ++){ int tmpx, tmpy; scanf("%d%d", &tmpx, &tmpy); //边读边做,不用数组 maxx = my_max(maxx, tmpy - tmpx); //更新最长有人挤奶时间的最大值 maxy = my_max(maxy, tmpx - lasttmp);//更新最长无人挤奶时间的最大值 lasttmp = tmpy; //更新上一次挤奶的结束时间 } printf("%d %d", maxx, maxy); //输出 return 0; }如果像我这样提交的话,结果是这样的:

为什么是错误的呢?我想了半天没想出来,于是使用了测试数据下载。第一个测试点是这样的:
1 100 200这样的话,lasttmp是0,而且输入的数据不一定是顺序的。所以,我们需要对数据排序。如果自己手写排序的话,性能很差。所以,我们使用<algorithm>里面的sort函数对我们的数据进行排序。下面我来介绍以下sort的用法
sort在<algorithm>里面,原型有两个:
template <class RandomAccessIterator> void sort(RandomAccessIterator first, RandomAccessIterator last); template <class RandomAccessIterator, class Compare> void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp);第一种原型是对一个数组进行默认的升序排序,第二种却是对数组进行自定义规则的排序。
comp这个参数是一个函数。它对两个和数组类型相同的数进行自定义的比较,如果返回true则不交换,否则交换。对一个有10个元素的数组进行排序,是这样的:
sort(a, a + 10, cmp);但是,这样使用sort只能排序一组数字。所以,我们使用结构体,使用自定义的cmp函数对整个数据进行排序。具体思路如下图:

但是,如何定义结构体呢?定义结构体的关键字是struct,是structure的简写。具体格式如下:
struct 结构体名{ 成员变量; 成员函数; }; 结构体名 变量;结构体在面向对象编程时很有用。但是,它也是sort的绝佳搭档。因为排序时,我们要对一个对象的每一条信息进行交换,而使用数组并不能实现这个功能,所以,使用结构体可以帮助我们完成很多复杂的排序问题。具体参考:
洛谷试炼场普及练习场排序与排序ex
这道题目,我们一个结构体存储每一条信息的和,进行排序,并按图上的思路输出。
#include <bits/stdc++.h> using namespace std; int N; struct node{ int begin, end; }m[5005]; bool cmp(node a, node b){ return a.begin < b.begin; } int main(){ scanf("%d", &N); for(register int i = 1; i <= N; ++ i) scanf("%d%d", &m[i].begin, &m[i].end); sort(m + 1, m + 1 + N, cmp); int begin = m[1].begin; int end = m[1].end; int ans1 = 0, ans2 = 0; for(register int i = 2; i <= N; ++ i){ if(m[i].begin <= end) end = max(end, m[i].end); else{ ans1 = max(ans1, end - begin); ans2 = max(ans2, m[i].begin - end); begin = m[i].begin; end = m[i].end; } } ans1 = max(ans1, end - begin); printf("%d %d", ans1, ans2); return 0; }P.S 这个代码是我们机房的同学写的。这道题是我们考试题目第一题,我用的是第一种方法,而他用的就是这一种。
- 1
信息
- ID
- 205
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 2
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者