1 条题解

  • 0
    @ 2025-8-24 21:22:25

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 学而思李老师
    ด้้้้้็้้้็็็็็้้้้้็็็็็้้้้้้็็็็็้้้้้็็็็็้้้้้้็็็็็้้้้้็็็็็้้้้้้็็็็็้้้้้็็็็็้้้้้้็็

    搬运于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
    上传者