USACO1.2.1 Milking Cows(挤牛奶)

来源:互联网 发布:淘宝高端产品 编辑:程序博客网 时间:2024/06/10 00:39

Three farmers rise at 5 am each morning and head for the barn to milk three cows. The first farmer begins milking his cow at time 300 (measured in seconds after 5 am) and ends at time 1000. The second farmer begins at time 700 and ends at time 1200. The third farmer begins at time 1500 and ends at time 2100. The longest continuous time during which at least one farmer was milking a cow was 900 seconds (from 300 to 1200). The longest time no milking was done, between the beginning and the ending of all milking, was 300 seconds (1500 minus 1200).

Your job is to write a program that will examine a list of beginning and ending times for N (1 <= N <= 5000) farmers milking N cows and compute (in seconds):

  • The longest time interval at least one cow was milked.
  • The longest time interval (after milking starts) during which no cows were being milked.

PROGRAM NAME: milk2

INPUT FORMAT

Line 1: The single integer Lines 2..N+1: Two non-negative integers less than 1000000, the starting and ending time in seconds after 0500

SAMPLE INPUT (file milk2.in)

3300 1000700 12001500 2100

OUTPUT FORMAT

A single line with two integers that represent the longest continuous time of milking and the longest idle time.

SAMPLE OUTPUT (file milk2.out)

900 300

题目大意:

    读入一个有N个农民(1<=N<=5000)挤N头牛的工作时间列表(起止时间),计算以下两点(均以秒为单位):
    • 最长至少有一人在挤奶的时间段.
    • 最长的无人挤奶的时间段.

解题思路:网上说有三种思想 

    <1>离散化(其实就是进行了优化的搜索而已)

       按照开始时间升序排序,然后从左到右扫一遍,复杂度是O(nlogn+n),(排序+扫一遍,用堆、合并、快排都可以)

    <2>线段树:本题的规模是1e6,简单的模拟是O(nm)(n是奶牛个数,m是最大范围)的,会超时。(但是本题数据远没有描述的那么恐怖,直接模拟也是很快的),

       用线段树统计区间,复杂度降为O(nlogm+m),可以接受。

    <3>标记数组(哈希)

本人认为其实用模拟比较好,在下是先排序,在从前到后扫描一遍,以下是我的代码:

/*USER:xingwen wangTASK:milk2LANG:C++*/#include<cstdio>#include<algorithm>/*调用sort函数的头文件*/ struct node{    int a,b;}N[5001];bool cmp(node x,node y){     return x.a<y.a; /*说明sort函数是升序还是降序排序*/ }int main(){    freopen("milk2.in","r",stdin);    freopen("milk2.out","w",stdout);    int i,j,k,end,n,max1,max2,ans;    scanf("%d",&n);    for(i=1;i<=n;i++)    scanf("%d%d",&N[i].a,&N[i].b);    std::sort(N+1,N+n+1,cmp); /*结构体排序,按元素a进行升序排序*/     ans=N[1].b-N[1].a;    end=N[1].b;    max1=ans;    max2=0;    for(i=2;i<=n;i++)    {        if(N[i].a>end)        {               ans=N[i].b-N[i].a;               if(N[i].a-end>max2)               max2=N[i].a-end;               end=N[i].b;        }        else if(N[i].a<=end&&N[i].b>end)        {               ans+=N[i].b-end;               end=N[i].b;        }        if(ans>max1)        max1=ans;    }    printf("%d %d\n",max1,max2);    return 0;}