JZOJ 【NOIP2017提高A组模拟9.14】捕老鼠

JZOJ 【NOIP2017提高A组模拟9.14】捕老鼠

题目

Description

为了加快社会主义现代化,建设新农村,农夫约(Farmer Jo)决定给农庄里的仓库灭灭鼠。于是,猫被农夫约派去捕老鼠。
猫虽然擅长捕老鼠,但是老鼠们太健美了,身手敏捷,于是猫想到了一个绝妙的办法:它决定点燃纯艾条,用烟熏老鼠。
农夫约的农庄里有N 个仓库,排成了一排,编号为1~N。
假设猫在第i 个仓库点燃艾条,烟雾就会充满该仓库,并向左右扩散Ai的距离,接着所有|i-j|<=Ai 的仓库j 的老鼠被消灭。
猫是一只爱护空气环境的好猫,它希望知道最少需要多少支艾条,才可以消灭所有老鼠。

Input

第一行:一个正整数,代表N。
第二行:N 个非负整数,第i 个数代表Ai。

Output

第一行:一个整数,代表答案。

Sample Input

10
2 0 1 1 0 3 1 0 2 0

Sample Output

3

Data Constraint

20%的数据:N <= 20
60%的数据:N <= 10^3
100%的数据:N <= 5*10^5,Ai <= N

题解

把艾条扩成一个区间
这题就是问最少多少条线段覆盖(1)~(n)
(c[i])表示当前这个位置的最大右烟熏位置
保证(c[i])递增,(c[i]>=c[i-1])
这样的话就可以分成一块一块
那么求块数就可以了
(i)表示当前的位置
那么下个(i)可以直接到(c[i+1])

Code

#include<cstdio>
#include<iostream>
using namespace std;
int n,now,ans,a[500005],c[500001];
int read()
{
	int res=0,fh=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if (ch=='-') fh=-1,ch=getchar();
	while (ch>='0'&&ch<='9') res=(res<<1)+(res<<3)+(ch-'0'),ch=getchar();
	return res*fh;
}
int main()
{
	freopen("cat.in","r",stdin);
	freopen("cat.out","w",stdout);
	n=read();
	for (int i=1;i<=n;++i)
		a[i]=read();
	for (int i=1;i<=n;++i)
		if (c[max(1,i-a[i])]<i+a[i]) c[max(1,i-a[i])]=i+a[i];
	for (int i=2;i<=n;++i)
		if (c[i]<c[i-1]) c[i]=c[i-1];
	while (now<=n) ++ans,now=c[now+1];
	printf("%d
",ans);
	fclose(stdin);
	fclose(stdout);
	return 0;
}
原文地址:https://www.cnblogs.com/Livingston/p/13906283.html