USACO-Chapter1-Section 1.2-Milking Cows (milk2)

【题目描述】

      三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶。第一个农民在300秒(从5点开始计时)给他的牛挤奶,一直到1000秒。第二个农民在700秒开始,在 1200秒结束。第三个农民在1500秒开始2100秒结束。期间最长的至少有一个农民在挤奶的连续时间为900秒(从300秒到1200秒),而最长的无人挤奶的连续时间(从挤奶开始一直到挤奶结束)为300秒(从1200秒到1500秒)。

你的任务是编一个程序,读入一个有N个农民(1 <= N <= 5000)挤N头牛的工作时间列表,计算以下两点(均以秒为单位):

  • 最长至少有一人在挤奶的时间段。
  • 最长的无人挤奶的时间段。(从有人挤奶开始算起)

【输入格式】

      Line 1:

一个整数N。

      Lines 2..N+1:

      每行两个小于1000000的非负整数,表示一个农民的开始时刻与结束时刻。

【输出格式】

      一行,两个整数,即题目所要求的两个答案。

【输入样例】

3
300 1000
700 1200
1500 2100

【输出样例】

900 300

【思路】

      这是一道类似于线段树的题目,因为数据太小,所以可以在O(n)的时间内查找计算首先对时间从小到大排序,然后用aa,bb分别记录下当前区间的最大最小值,如果新输入的值在此内,跳过,如果不在则判断是否范围比之前的更大,如果是更新。如果改次查找的值下界比区间最大值还大,应该是遇到了间断,此时判断并比较记录。(打擂更替)

【算法代码】

      时间复杂度[O(n*log(n)+n)]

      空间复杂度[O(n)]

  • Executing...
  • Test 1: TEST OK [0.000 secs, 316 KB]
  • Test 2: TEST OK [0.000 secs, 316 KB]
  • Test 3: TEST OK [0.000 secs, 316 KB]
  • Test 4: TEST OK [0.000 secs, 316 KB]
  • Test 5: TEST OK [0.000 secs, 316 KB]
  • Test 6: TEST OK [0.000 secs, 316 KB]
  • Test 7: TEST OK [0.000 secs, 316 KB]
  • Test 8: TEST OK [0.011 secs, 316 KB]
  • All tests OK.
{
 ID  : c_CaM.19
 LANG: PASCAL
 TASK: milk2
}
Program CaM(input,output);
Var
  a,b:array[0..5100] of longint;
  aa,bb,n,ans1,ans2,i,j:longint;

Procedure innt;
Begin
  assign(input,'milk2.in'); reset(input);
  assign(output,'milk2.out'); rewrite(output);
End;

Function max(x,y:longint):longint;
Begin
  if x<y then exit(y) else exit(x);
End;

Procedure outt;
Begin
  close(input);
  close(output);
End;

Procedure qs(x,y:longint);
Var
  mid,i,j,t:longint;
Begin
  i:=x; j:=y; mid:=a[(x+y)div 2];
  repeat
    while a[i]<mid do inc(i);
    while a[j]>mid do dec(j);
    if i<=j then Begin
                   t:=a[i]; a[i]:=a[j]; a[j]:=t;
                   t:=b[i]; b[i]:=b[j]; b[j]:=t;
                   inc(i); dec(j);
                 End;
  until i>j;
  if x<j then qs(x,j);
  if i<y then qs(i,y);
End;

Begin
  innt;
  readln(n);
  for i:=1 to n do
    read(a[i],b[i]);
  qs(1,n);
  ans1:=b[1]-a[1]; aa:=a[1]; bb:=b[1];
  for i:=2 to n do
  Begin
    if b[i]<=bb then continue;
    if (b[i]>bb)and(a[i]<=bb) then
    Begin
      ans1:=max(ans1,b[i]-aa);
      bb:=b[i];
      continue;
    End;
    if a[i]>bb then
    Begin
      ans2:=max(ans2,a[i]-bb);
      aa:=a[i];
      bb:=b[i];
    End;
  End;
  writeln(ans1,' ',ans2);
  outt;
End.
posted @ 2012-02-16 00:39  你滴韩王  阅读(345)  评论(0)    收藏  举报