【二分】丢瓶盖

二分答案

题目描述

陶陶是个贪玩的孩子,他在地上丢了A个瓶盖,为了简化问题,我们可以当作这A个瓶盖丢在一条直线上,现在他想从这些瓶盖里找出B个,使得距离最近的2个距离最大,他想知道,最大可以到多少呢?

输入输出格式

输入格式:

 

第一行,两个整数,A,B。(B<=A<=100000)

第二行,A个整数,分别为这A个瓶盖坐标。

 

这不是2017年衢州市赛的题目么

借用题解里看到的一句话总结一下:“一般看到所谓的最大值最小化或者最小值最大化,一般都是用二分答案进行运算”作者: Lyrics 

嗯对了就是这样,二分答案。

二分答案的题呃普及组的似乎就是这样的套路:找一个上下限;写一个check函数;考虑输出 mid / l / r。最后这个还是视情况而定。

本题的话,check函数不难写出,不过我卡在了最后的这个输出上面。因为以前有写二分的“阴影”,调试的时候先把三个都列出来了。呃,还有那个调整上下限的问题,我印象里"l=mid"/"l=mid+1"在不同的题目里都有出现。于是乎调整了很久(有调将近二十分钟),最后没有办法打了个类似于补丁一样的东西上去(好吧这的确很不“计算机程序设计艺术”),大号提交的是这份:

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int a[100035],n,m;
 5 int l,r,mid,lm,la,cnt;
 6 int main()
 7 {
 8     scanf("%d%d",&n,&m);
 9     for (int i=1; i<=n; i++)scanf("%d",&a[i]);
10     sort(a+1, a+n+1);
11     l=0;r=a[n]-a[1];lm = -1;
12     while (l <= r)
13     {
14         mid = (l + r) >> 1;
15         if (mid == lm)break;
16         la=1;cnt=1;
17         for (int i=2; i<=n; i++)
18             if (a[i] - a[la] >= mid){
19                 cnt++;la = i;
20             }
21         if (cnt < m)r = mid-1;
22         else l = mid+1;
23         lm = mid;
24     //    printf("%d %d %d\n",l,r,mid);
25     }
26     {
27         while(cnt < m)
28         {
29             mid--;
30             la=1;cnt=1;
31             for (int i=2; i<=n; i++)
32                 if (a[i] - a[la] >= mid){
33                     cnt++;la = i;
34                 }
35         }
36     }
37     printf("%d",mid);
38     return 0;
39 } 
大号份 ViewCode

 

嗯,地地道道的丑陋……

看了一下题解,突然想起来这里求最大值,所以不用费神这么多,输出r就行了。不过当时在前几次的调试之后(调整上下限的还没成型),发现l,r都不对,最后决定改成mid了……

小号份ViewCode

 

 

噫,好吧二分是不太熟了

 

 1 笨蛋我的方法
 2 int main()
 3 {
 4     l=0;r=a[n]-a[1];lm = -1;
 5     while (l <= r)
 6     {
 7         mid = (l + r) >> 1;
 8         if (mid == lm)break;
 9         la=1;cnt=1;
10         for (int i=2; i<=n; i++) ...
11         if (cnt < m)r = mid-1;
12         else l = mid+1;
13         lm = mid;
14     }
15     {
16         while(cnt < m)
17         {
18             mid--;
19             la=1;cnt=1;
20             for (int i=2; i<=n; i++)
21                 if (a[i] - a[la] >= mid){
22                     cnt++;la = i;
23                 }
24         }
25     }
26     printf("%d",mid);
27     return 0;
28 }
29 
30 
31 聪明你的方法
32     l=0;r=a[n]-a[1];
33     while (l <= r)
34     {
35         mid = (l + r) >> 1;
36         la=1;cnt=1;
37         for (int i=2; i<=n; i++)
38             if (a[i] - a[la] >= mid){
39                 cnt++;la = i;
40             }
41         if (cnt < m)r = mid-1;
42         else l = mid+1;
43     }
44     printf("%d",r);
45     return 0;

 

posted @ 2018-02-22 20:19  AntiQuality  阅读(332)  评论(0编辑  收藏  举报