题意:给出一些点和这些点能延伸的距离,标记最少的点使得所有的点都可以被标记到(一个点能左右延伸到另一个点,则另一个点视为被标记)。
分析:走弯路了。。。直接贪心用循环从最做边开始走就行了。。。结果。。我一开始不知怎么着想错了。。。用的二分查找加减之后的最大值。。。。结果一直时间超限。。看了书之后突然意识到。。直接循环就行啊。这样也就从最左边到最右边。时间复杂度仅仅是o(n)。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxed=1000+10;
int p[maxed],n,r;
int main()
{
while(scanf("%d%d",&r,&n)!=EOF){
if(n==-1&&r==-1)
break;
for(int i=0;i<n;i++)
scanf("%d",&p[i]);
sort(p,p+n);
int i=0,ans=0;
while(i<n){
int x=p[i++];
while(i<n&&p[i]<=x+r)
i++;
if(i<n&&p[i]!=x+r)
i--;
x=p[i];
while(i<n&&p[i]<=x+r)
i++;
if(i<n&&p[i]==x+r)
i++;
ans++;
}
printf("%d\n",ans);
}
return 0;
}
最后再把自己脑残的二分代码放上吧。。引以为戒。:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxed=1000+10;
int p[maxed],n,r;
int main()
{
while(scanf("%d%d",&r,&n)!=EOF){
if(n==-1&&r==-1)
break;
for(int i=0;i<n;i++)
scanf("%d",&p[i]);
sort(p,p+n);
int wa=0,ans=0;
while(true){
if(wa>n-1)
break;
int x=p[wa]+r;
if(x>=p[n-1]){
ans++;
break;
}
int a=lower_bound(p,p+n,x)-p;
if(p[a]!=x)
a-=1;
wa=lower_bound(p,p+n,p[a]+r)-p;
if(p[wa]==p[a]+r)
wa+=1;
ans++;
}
printf("%d\n",ans);
}
return 0;
}