USACO-Milking Cows
http://ace.delos.com/usacoprob2?a=aGfy6bAUEQK&S=milk2
这题做法比较多了,不过也离不开排序。是排开始的时间?排结束的时间?我的做法是,两个一起排!
转化为类似于括号的配对问题,不过有些细节要注意好了。
#include <iostream> #include <string.h> #include <cstdio> #include <algorithm> using namespace std; struct node{ int data; //时间点 bool flag; //标记开始时间和结束时间 node() { data=0; flag=false; } friend bool operator < (node a,node b) { return (a.data<b.data)||(a.data==b.data && !a.flag); //这里排序一定要处理好特殊情况 } }; int main() { freopen("milk2.in","r",stdin); freopen("milk2.out","w",stdout); struct node a[100005]; int n,x,y,len=0; scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%d%d",&x,&y); a[++len].data=x; a[len].flag=false; a[++len].data=y; a[len].flag=true; } sort(a+1,a+n*2+1); int max1=0,max2=0; int h=0,s=0,d=0,m=n*2; for (int i=1;i<=m;i++) //类似于括号的配对问题,但是更简单 { if (!a[i].flag) { if (h==0) h=i; s++; } if (a[i].flag) { s--; if (s==0) { if (a[i].data-a[h].data>max1) max1=a[i].data-a[h].data; h=0; if (a[i+1].data-a[i].data>max2) //记住,没有牛挤奶的时间段,必定是前一个结束时间和后一个开始时间的时间差 max2=a[i+1].data-a[i].data; } } } cout<<max1<<" "<<max2<<endl; return 0; }
排序时一定要加上两个时间相等的情况,例如:
6
100 200
200 400
400 800
800 1600
50 100
1700 3200
如果不加时间相等的情况,输出是:1500 100
而正确答案是:1550 100
而且相等时要把开始的时间放前面,若放后边,配对时同一个时间点的开始时间和结束时间直接配对,这不是我们想看到的。。。
其他的方法,例如排序开始时间,然后在慢慢判断结束时间。。。额。。。还是直接排序比较直观方便吧。。。。。