首页 > 其他 > 详细

二分答案&【NOIP 2015】跳石头

时间:2018-08-26 20:41:09      阅读:189      评论:0      收藏:0      [点我收藏+]

二分答案估计是我应该早就学会,但拖到现在才去好好看的套路吧!

二分答案是指在答案具有单调性的前提下,利用二分的思想枚举答案,将求解问题转化为验证结果。首先需要估计答案的上下界,然后不断取区间中点进行验证(这就要求答案的验证应当简单可行),并通过验证结果不断更新答案区间,最终得到答案。不难看出,朴素的枚举验证时间复杂度是O(n)的,而二分可以做到O(logn)。更令人欣喜的是,二分答案的问题往往有固定的问法,比如:令最大值最小(最小值最大),求满足条件的最大(小)值等。

 

一道模板题练个手:https://www.luogu.org/problemnew/show/P2678


 

这几乎是最简单的二分答案模板题,在明白二分答案后,是可以做到一遍AC的。题目的问法也十分模板(求最短跳跃距离的最大值),答案是单调的,拿走的石头越多,最短跳跃距离越大。我们可以估计最大的最短跳跃距离(1<=ans<=L)。然后取区间中点,进行验证。若发现某次跳跃比这个最短跳跃距离还小,那就把这块石头拿走。总共拿走的石头数不超过M,就说明区间中点符合要求,就将区间更新为右半区间(因为要求最大的最短跳跃距离);反之,就将区间设为左半区间。

技术分享图片
 1 #include<cstdio>
 2 #include<cctype>
 3 inline int get_num() { //读入优化
 4     int num;
 5     char c;
 6     while((c=getchar())==\n||c== ||c==\r);
 7     num=c-0;
 8     while(isdigit(c=getchar())) num=num*10+c-0;
 9     return num;
10 }
11 const int maxn=5e4+5;
12 int L,n,m,d[maxn];
13 bool check(int x) { //检验答案是否符合要求
14     int last=0,cnt=0;
15     for(int i=1;i<=n;++i) {
16         if(d[i]-last<x) ++cnt; //拿走石头
17         else last=d[i]; //跳出不影响答案的一步
18     }
19     return cnt<=m?true:false;
20 }
21 int main() {
22     L=get_num();n=get_num();m=get_num();
23     for(int i=1;i<=n;++i) d[i]=get_num();
24     d[++n]=L; //注意,最终要跳到终点
25     int l=0,r=L+1;
26     while(r-l>1) {
27         int mid=l+(r-l)/2;
28         if(check(mid)) l=mid; //调整区间
29         else r=mid;
30     }
31     printf("%d",l);
32     return 0;
33 }
AC代码

 

二分答案&【NOIP 2015】跳石头

原文:https://www.cnblogs.com/Mr94Kevin/p/9538431.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!