洛谷2678 跳石头
原题链接
交题记录
22:28 AC
题解
这次做这个题主要是为了填一下二分答案的坑。。。
由于某些细节问题处理不当一直没写出来。。。。。
现在终于搞清楚了。。。
以后去多做几道相关的题。。。
二分答案,我理解为通过二分的方式来求得答案,以代替枚举,将\(O(n)\)的枚举降到\(O(log_2n)\)的枚举
条件?满足单调性,即是否可行与决策的关系是这样的:1111111111111110000000000000000000000
0000000000000000001111111111111111111111
111110000
01111111111111
而不是这样的:010000000000000000
1000000000000000010
等等。
只要\(i\)可行,所有\(j>i\)(\(j<i\))也都可行。
如何枚举?设l,r,表示答案只会在\([l,r]\)中出现。
核心:check函数
当然也可以写成别的。
当check返回1时,视为可行,返回0时,不可行。当然可以根据喜好改变
按上面来。假设只要\(i\)可行,所有\(j<i\)也都可行(也就是本题的形式)。
while(l<r){
mid=l+r>>1;
if(check(mid+1))l=mid+1;
else r=mid;
}
二分答案有很多版本,随便了。。。
我用上面的模板
在\([l,r]\)中取一个\(mid\)并对\(mid+1\)进行check(为什么?因为mid向下取整,如果l=1,r=2就会一直死循环下去)
mid+1可行:l=mid+1.因为\([1,mid+1]\)都可行,此时\(mid+1\)更优
mid+1不可行:后面都不可行,r=mid.
Code
// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
typedef long long ll;
il int gi(){
rg int x=0,f=1;rg char ch=getchar();
while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int maxn=50010,maxm=maxn<<1;
int d[maxn],L,n,m;
il bool check(int ans){
int last=0,sum=m;
rep(i,1,n)
if(d[i]-last<ans){
if(sum)--sum;
else return 0;
}
else last=d[i];
return 1;
}
int main(){
L=gi(),n=gi()+1,m=gi();
rep(i,1,n-1)d[i]=gi();
d[n]=L;
int mid,l=1,r=L;
while(l<r){
mid=l+r>>1;
if(check(mid+1))l=mid+1;
else r=mid;
}printf("%d\n",l);
return 0;
}
没了。。。