zoukankan      html  css  js  c++  java
  • 【洛谷习题】丢瓶盖

    题目链接:https://www.luogu.org/problemnew/show/P1316


    刷新我对二分答案理解的二分答案题!

    根据问法这是道二分答案题,嗯事实证明确实如此。然后我们分两个过程研究。

    第一是二分边界的处理。之前我一直使用的是闭区间,结果在这翻车了,我之前还以为闭区间是万能的,左闭右开是不完美的!!!额,原因在于闭区间对于边界的处理十分严格,编程语言的缘故,就会出现死循环等不可描述的错误。

    解决办法是区间不要卡得太严格,要写成mid=l+(r-l+1)/2。当然也可以改成左闭右开,就比较自然了。后来发现,其实两种方法在不同的情况下并不一定正确,一个比较不正式的方法是,两种方法都试试。

    第二点就是验证了。一开始我很纠结,两个瓶盖的最短距离必须保证存在啊,仔细考虑后发现,最大的最短距离一定是存在的,就是说一定有两个瓶盖的距离是他,否则,会存在两个瓶盖的距离比这个答案还大。

    再就是,验证时,我们从1开始暴力验证,能取就取,真的对吗?应该是对的,要么符合答案的取法里有1,要么没有,如果没有,若答案会取的那个在1的下一块之后,那么和1就没有什么关系了,若刚好是1的下一块,显然取1会更优(当然,如果答案不是1和其下一块的距离,和1就更没有关系了)。

    呃呃,还要注意将坐标排序,题目描述并不保证是顺序的。

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 using namespace std;
     5 
     6 const int maxn = 1e5 + 5;
     7 
     8 int a, b, cap[maxn];
     9 
    10 inline int min(int a, int b) {return a < b ? a : b;}
    11 
    12 inline int check(int x) {
    13     int cnt = 1, last = 1;
    14     for (int i = 2; i <= a; ++i)
    15         if (cap[i] - cap[last] >= x) ++cnt, last = i;
    16     if (cnt >= b) return 1;
    17     else return 0;
    18 }
    19 
    20 int main() {
    21     scanf("%d%d", &a, &b);
    22     for (int i = 1; i <= a; ++i)
    23         scanf("%d", &cap[i]);
    24     sort(cap + 1, cap + a + 1);
    25     int l = 0, r = cap[a] - cap[1], mid;
    26     while (l < r - 1) { //左闭右开写法
    27         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代码
  • 相关阅读:
    【SQL】行转列
    【SQL】高级函数汇总
    VisualStudio优秀扩展插件推荐
    【SQL】多行转一列 FOR XML PATH
    【SQL】判断一个字符串是否在另外一个字符串中
    【NodeJS】Windows环境初始化
    【WPF】实现加载中动画效果
    C# ffmpeg简单帮助类
    ZSH出现问题
    Manjaro 安装后的配置
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9777352.html
Copyright © 2011-2022 走看看