USACO 1.3 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.

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

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

 • 最长至少有一人在挤奶的时间段.  

• 最长的无人挤奶的时间段. 


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}。 看不懂?去看看 PASCAL 或 C 的范例程序就明白了。

 线段树 

本题的规模是 1e6,简单的模拟是 O(nm)(n 是奶牛个数,m 是最大范围)的,会超时。 (但是本题数据远没有描述的那么恐怖,直接模拟也是很快的)。用线段树统计区间,复杂度降为 O(nlogm+m),可以接受。

标记数组(哈希)

1e6的范围,开一个布尔数组完全可以,有人为 TRUE,无人为 FALSE,注意边界即可。 最后线性扫描即可。 时间复杂度,应该是 O(n),n 为最后结束的时间。缺点就是……比较慢。叫什么好呢? 并查集加速直接模拟。 记录一个 fa[i]表示 i 之后第一个没覆盖的点。下次遇到这里的时候就可以直接跳过了。 复杂度大概算 o(n)吧。

代码如下:
/*
ID: zhaoxia13
LANG: C
TASK: milk2
*/

#include <stdio.h>
#include <stdlib.h>


int main()
{
	freopen("milk2.in", "r", stdin);
	freopen("milk2.out", "w", stdout);

	int n, i, j, da = -10, xiao = 999999, a = 0, b = 0, flag = 1;
	int begin, end, num[299999] = {0};
	scanf("%d", &n);
	while(n--)
	{
		scanf("%d %d", &begin, &end);
		if(begin < xiao)
			xiao = begin;
		if(end > da)
			da = end;
		for(j = begin; j < end; j++)
			num[j] = 1;
	}

	for(i = xiao; i < da;)
	{
		j = i;
		if(flag == 1)
		{
			for(; num[i] == 1 && i <= da; i++)
				flag = 0;
			if(i - j > a)
				a = i - j;
		}
		else if(flag == 0)
		{
			for(; num[i] == 0 && i <= da; i++)
				flag = 1;
			if(i - j > b)
				b = i - j;
		}

	}

	printf("%d %d\n", a, b);

	fclose(stdin);
	fclose(stdout);

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值