USACO Milking Cows (模拟)

原创 2017年10月05日 13:30:10
Milking Cows

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, N
Lines 2..N+1: Two non-negative integers less than 1,000,000, respectively the starting and ending time in seconds after 0500

SAMPLE INPUT (file milk2.in)

3
300 1000
700 1200
1500 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


半官方题解:

有四种思想

[编辑]离散化

(其实就是进行了优化的搜索而已)

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

所谓从左到右扫一遍,就是记录一个当前区间,[tmp_begin , tmp_end]

如果下一组数据的begin比tmp_end的小(或相等),则是连接起来的,检查这组数据的end,取max{end , tmp_end}。

如果下一组数据的begin比tmp_end的大,则是相互断开的,整理本区间,ans1取max{tmp_end - tmp_begin , ans1}。ans2取max{begin - tmp_end , ans2}


我觉得其实是不用排序的

设bi,ei分别为第i个输入inc(map[bi]);dec(map[ei])

记录下min_x和max_y,从min_x到max~y-1扫描,分别统计最大的连续0的个数、连续非零数的个数

缺点是代码很长啊。。

[编辑]线段树

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

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

[编辑]怀疑是线段树的变形?

把每个输入看作是一个所谓的“线段”,只有开头和结尾。

既然每条线段有重叠现象,马上想出可以合并!按照开头和结尾从小到大排序,for一遍,如果发现前后两条线段开头与结尾重叠了,

(当然也要考虑被完全包括的情况),马上修改开头与结尾,并删除(可以标记),最后在剩下的线段中统计就可以了。

(好像非常易懂,也很容易实现)

[编辑]标记数组(哈希)

1e6的范围,开一个布尔数组完全可以,有人为TRUE,无人为FALSE,注意边界即可。最后线性扫描即可。

时间复杂度,应该是O(n),n为最后结束的时间。

缺点就是……比较慢


和我的方法比较像,但我做了些优化

预处理:

建立一个数组a。

读入,若为起点将a[i]加1,若为终点将a[i]减1。

(这时顺便找出总的起点与终点);

算法开始:

将数组扫一遍(注意从总的起点扫到总的终点),这时将x(初始为0)加上a[i]。

若遇到x由0变1,或由1变0,

将这个点计入数组ans[]。

然后再将ans扫描一遍,大家可能都想到了:

若i为奇数,ans[i+1]-ans[i] 应该是有人的时间间隔;

若i为偶数,反之。

这个算法是O(n),实际效果不错,但我也不知道应该叫什么。

回楼上的话,这种方法可以称之为是差分。见noip2012提高组 借教室。具体指有一列数字a,

再找来一个数组s记录相邻数字之差,这样每个数字a[i]都是s[1]+s[2]+...+s[i-1]。对于一

段数字的加减法就可以通过将这一段开头的差加上相应的数字,再把这一段结尾的数字减去相

应的数值即可。很巧妙的方法。

[编辑]叫什么好呢?并查集加速直接模拟

记录一个fa[i]表示i之后第一个没覆盖的点。 下次遇到这里的时候就可以直接跳过了。 复杂度大概算o(n)吧。

[编辑]分段动规

消逝者--183.16.23.147 22:26 2011年11月3日 (CST)

时间复杂度(nlogn),全部0毫秒。

以开始时间从小到大快排每个农民

快排后:

f[i]表示第i个农民所在的最长连续线段

last_start表示这个线段的起点。

a[i].begin 第i个农民的起点时间,a[i].end 终点时间

可以得出方程:

f[i]={max{f[i-1],a[i].end} (a[i].begin<=f[i-1]) //加上第i个农民仍然连续
      a[i].end             (a[i].begin>f[i-1])  /*加上第i个农民变不连续 
                                                  在这里开始以此农民的开始时间的新的一条连续线段,
                                                  更新last_start=a[i].begin作为新起点,因为有间隔,
                                                  所以更新longest_idle_time=max(longest_idle_time,a[i].begin-f[i-1]);*/

在每次循环处理后longest_continuous_time=max(longest_continuous_time,f[i]-last_start) 最后输出longest_continuous_time和longest_idle_time即可。


在我看来,不就是排个序,然后跑下标,判断开始和结束的时间,然后O(n)跑一遍不就完了吗?然而就是搞不定啊,邪门啊,最多过两组示例,然后发现右端点要记录最大值,还是乖乖写篇博客,记录一下这坑人的一题,WA两天,折磨。

代码实现:

/*
  ID : ever g1
  PROG : milk2
  LANG : C++
*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<cstdio>
#define ll long long
#define mset(a,x) memset(a,x,sizeof(a))

using namespace std;
const double PI=acos(-1);
const int inf=0x3f3f3f3f;
const double esp=1e-6;
const int maxn=100005;
const int mod=1e9+7;
int dir[4][2]={0,1,1,0,0,-1,-1,0};
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll inv(ll b){if(b==1)return 1; return (mod-mod/b)*inv(mod%b)%mod;}
ll fpow(ll n,ll k){ll r=1;for(;k;k>>=1){if(k&1)r=r*n%mod;n=n*n%mod;}return r;}
struct node{
	int l,r;
}p[5005];

int cmp(node a,node b)
{
	if(a.l==b.l)
	return a.r<b.r;
	
	return a.l<b.l; 
}

int main()
{
	freopen("milk2.in","r",stdin);
	freopen("milk2.out","w",stdout);
    int n,i,j,k,minn,maxx,visit[5005];
    cin>>n;
    for(i=0;i<n;i++)
    cin>>p[i].l>>p[i].r;
    
    sort(p,p+n,cmp);
    int l=p[0].l,r=p[0].r;
    if(n==1)
    {
    	cout<<p[0].r-p[0].l<<' '<<"0"<<endl;
    	
    	goto q;
	}
    
    i=1;minn=maxx=0;
    while(i<n)
    {
    	while(i<n&&p[i].l<=r)
    	{
    		if(p[i].r>r)
    		r=p[i].r;
    		
    		i++;
		}
		if(r-l>maxx)
		maxx=r-l;
		if(i==n)
		break;
		if(p[i].l-r>minn)
		minn=p[i].l-r;
		
		l=p[i].l;r=p[i].r;
		i++;
	}
    cout<<maxx<<' '<<minn<<endl;
q:	return 0;
}


版权声明:欢迎转载,请注明此博客地址。

USACO-Section 1.2 Milking Cows[数组模拟]

这道题的基本想法就是,利用数组模拟。开一个布尔型的标记数组,若标记值为true,表明这个时间是至少有一头牛是出于被喂奶的状态的。在输入每个农名的时间段的时候,可以用memset方法直接填充那个时间段。...

【USACO题库】1.2.1 Milking Cows挤牛奶(模拟)

【USACO题库】1.2.1 Milking Cows挤牛奶

【USACO-Chapter1-1.2】【模拟】Milking Cows

【题目描述】 三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶。第一个农民在300秒(从5点开始计时)给他的牛挤奶,一直到1000秒。第二个农民在700秒开始,在 1200秒结束。第三个农民在1...
  • njlcazl
  • njlcazl
  • 2012年06月17日 17:54
  • 1117

【模拟】洛谷 P1204 [USACO1.2]挤牛奶Milking Cows

题目描述三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶。第一个农民在300秒(从5点开始计时)给他的牛挤奶,一直到1000秒。第二个农民在700秒开始,在 1200秒结束。第三个农民在1500秒开始...

USACO题目Milking Cows及代码解析

  • 2012年10月23日 23:04
  • 16KB
  • 下载

USACO 1.2 Milking Cows

Milking Cows  方法1: 动态规划? y

USACO1.2.1 Milking Cows(挤牛奶)

Three farmers rise at 5 am each morning and head for the barn to milk three cows. The first farmer b...
  • gswxw
  • gswxw
  • 2013年01月08日 16:01
  • 1106

USACO Milking Cows 解题日志

因为过年,加上被窝太温暖,加上……总之好久没有做题了。 先把题目贴上来。 Milking Cows Three farmers rise at 5 am each morning a...

Usaco 1.2.1 挤牛奶(Milking Cows)

题目:  挤牛奶 来源:  Usaco1.2.1 题目大意:  给定N个人,每个人有个开始时间和结束时间,求最长的无人时间和最长的有人时间 数据范围:  1 ...

USACO Section 1.2.2 Milking Cows

题目 Milking Cows Three farmers rise at 5 am each morning and head for the barn to milk ...
  • kzzhr
  • kzzhr
  • 2013年03月04日 22:23
  • 1092
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:USACO Milking Cows (模拟)
举报原因:
原因补充:

(最多只允许输入30个字)