題意:給出一些點和這些點能延伸的距離,標記最少的點使得所有的點都可以被標記到(一個點能左右延伸到另一個點,則另一個點視爲被標記)。
分析:走彎路了。。。直接貪心用循環從最做邊開始走就行了。。。結果。。我一開始不知怎麼着想錯了。。。用的二分查找加減之後的最大值。。。。結果一直時間超限。。看了書之後突然意識到。。直接循環就行啊。這樣也就從最左邊到最右邊。時間複雜度僅僅是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;
}