这题应该如何正确思考?
先给了n个灯塔的位置和它们各自的摧毁范围,要求最后立的这个灯塔,它的作用实际上可以是:
保证你可以在[0,n]之间的任意位置 i 开始 激活灯塔,也就是说把[ i+1,n]这个范围的灯塔全部摧毁。
这样的话,可以设一个数组dp[maxn],计算在[0,maxn]之间 每一个 i(灯塔) 被激活时,在 [0,i] 范围内 存活的灯塔数量。
(即dp[i] 表示,第i个灯塔被激活时,[0,i]存活的灯塔数量。)
设一个max,为最大存活的灯塔数量,n-max 即为答案。
另,做这题得到一个好消息和一个坏消息。
好消息是,可以用
ios::sync_with_stdio(0);
cin.tie(NULL);
两个语句来加快 cin cout 的输入输出速度,这两句话的意思是,解除cin,cout与 stdio 的关系,不再兼容C 的输入输出。据说用了之后速度与scanf相差无几。
坏消息是:
经过亲测:本题 用了这两句+cin、cout是155ms,用printf、scanf是62ms............
代码:
#include <stdio.h>
using namespace std;
int b[1000005],dp[1000005]; //全局变量初始化为0,省去memset
int main()
{
int n,a;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a);
scanf("%d",&b[a]);
}
if(b[0]>0) //用 > 不用 != 因为 > 的判断貌似比!=要快
dp[0]=1;
int ans=0;
for(int i=1;i<1e6+5;i++)
{
if(b[i]==0)
dp[i]=dp[i-1];
else
{
if(b[i]>=i) //如果b[i]>i,则灯塔的范围肯定能全部覆盖[0,i-1],
dp[i]=1; //最后只剩下它自己
else
dp[i]=dp[i-b[i]-1]+1; //如果不是,摧毁掉其所能覆盖的范围后,+1(它本身)
}
if(dp[i]>ans)
ans=dp[i];
}
printf("%d\n",n-ans);
return 0;
}