首页 > 其他分享 >二分答案类型题目及小结

二分答案类型题目及小结

时间:2023-05-14 18:33:38浏览次数:42  
标签:二分 可行 题目 mid 这个 答案 小结 我们

洛谷 2678.跳石头
//考点:二分答案

二分答案思路:这道题如果要使用暴力搜索直接求解会严重超时。实际上,我们可以发现,这个所谓的最短跳跃距离显然不能超过一个范围,而这个范围题目上已经给了出来。也就是说,答案是有一个确定的范围限制的,我们就可以考虑一种另外的方法去解决——枚举答案,并去验证答案是否可行。

实际上,枚举答案有时候也会超时。这就好比说你要从一本英汉词典上查一个单词,你从头到尾一页一页的翻着找,这样找可以保证一定能找到,但是最坏情况你要把整本词典都翻一遍,那就麻烦了。

有什么改进的方法吗?当然有。

考虑把这个词典从中间分开,看一下中间那一页的主要单词都是啥,然后去判断我要找的单词应该在左半部分还是右半部分,再去那一部分考虑怎么找就好了。同样的,在另一部分也是要进行划分并且判断的操作。这样一直进行下去,便能很快的找到答案,而且根本不需要翻过整个词典来。

可以证明,如果一页一页的找,最多要找n次,但是用这个方法,最多找floor(log2n)次。

我们把这个方法叫做“二分答案”。顾名思义,它用二分的方法枚举答案,并且枚举时判断这个答案是否可行。但是,二分并不是在所有情况下都是可用的,使用二分需要满足两个条件。一个是有界,一个是单调。

二分答案应该是在一个单调闭区间上进行的。也就是说,二分答案最后得到的答案应该是一个确定值,而不是像搜索那样会出现多解。二分一般用来解决最优解问题。刚才我们说单调性,那么这个单调性应该体现在哪里呢?

可以这样想,在一个区间上,有很多数,这些数可能是我们这些问题的解,换句话说,这里有很多不合法的解,也有很多合法的解。我们只考虑合法解,并称之为可行解。考虑所有可行解,我们肯定是要从这些可行解中找到一个最好的作为我们的答案, 这个答案我们称之为最优解。

最优解一定可行,但可行解不一定最优。我们假设整个序列具有单调性,且一个数x为可行解,那么一般的,所有的x'(x'<x)都是可行解。并且,如果有一个数y是非法解,那么一般的,所有的y'(y'>y)都是非法解。

那么什么时候适用二分答案呢?注意到题面:使得选手们在比赛过程中的最短跳跃距离尽可能长。如果题目规定了有“最大值最小”或者“最小值最大”的东西,那么这个东西应该就满足二分答案的有界性(显然)和单调性(能看出来)。

那就好办了。我们二分跳跃距离,然后把这个跳跃距离“认为”是最短的跳跃距离,然后去以这个距离为标准移石头。使用一个judge判断这个解是不是可行解。如果这个解是可行解,那么有可能会有比这更优的解,那么我们就去它的右边二分。为什么去右边?答案是,这个区间是递增的 ,而我们求的是最短跳跃距离的最大值,显然再右边的值肯定比左边大,那么我们就有可能找到比这更优的解,直到找不到,那么最后找到的解就有理由认为是区间内最优解。反过来,如果二分到的这个解是一个非法解,我们就不可能再去右边找了。因为性质,右边的解一定全都是非法解。那么我们就应该去左边找解。整个过程看起来很像递归,实际上,这个过程可以递归写, 也可以写成非递归形式,我个人比较喜欢使用非递归形式。

下一个问题,这个judge怎么实现呢?judge函数每个题有每个题的写法,但大体上的思想应该都是一样的——想办法检测这个解是不是合法。拿这个题来说,我们去判断如果以这个距离为最短跳跃距离需要移走多少块石头,先不必考虑限制移走多少块,等全部拿完再把拿走的数量和限制进行比对,如果超出限制,那么这就是一个非法解,反之就是一个合法解,很好理解吧。

涉及模板:
while (l < r)
{
    int mid = l + r >> 1;
    if (check(mid)) r = mid;
    else l = mid + 1;
    /*mid = l +  r + 1 >> 1; l 先则mid处要+1
    if (check(mid)) l = mid;  
    else r = mid - 1;
    */
}
洛谷 1902.刺杀大使
//考点:二分答案,dfs;通过二分答案对dfs进行可行性优化

思路:/*读完题目之后,有一个比较明显的句子“ 整个部队的伤害值最小 。” 因为整个部队的伤害值是最大值那么这个题目就变成了最大值的最小值 所以我们考虑二分答案求解。*/

我们二分一个答案mid来表示一个界限,如果当前这个格子的伤害代价比mid小则可以走否则就不走,每次check函数只需判断能否从第一行走到最后一行即可,因为每一行的每个门都是相连的,所以只要有一个能到,那么我们再派m-1个人顺着这条路过去再沿着横向的门过去就好啦,因为第一行和最后一行的伤害值为零,所以这么做莫得问题。

解释一下我很久都没搞明白的问题:

为什么dfs时只要判断是否能到达即可,我们不是要找他的最大值来表示这一次的伤害值嘛? 因为我们二分的这个值,最后二分出来的一定是某个点产生的伤害值,也就是我们最后的答案(是最大值嘛,判断此点是否可行就是判断他是否是比mid小,所以mid就是此次的最大值就是答案)这也解释了为什么我们二分的是伤害值最后却可以输出二分的边界的问题。
洛谷 1314.聪明的质检员
//考点:前缀和,二分答案;通过前缀和快速计算一个区间某个属性的和,通过二分枚举降低时间复杂度
洛谷 1083.借教室
//考点:差分,二分答案;需要对一段区间整体进行加减操作,运用差分数组;正向思维一次次遍历得到答案,但是对答案进行分析发现具有二分性通过逆向思维思考对答案进行二分枚举
洛谷 4343.自动刷题机
//考点:通过二分判断一个区间的左右边界,划分为≥和≤使区间具有二分性,如果左边界≥右边界则表明不存在

标签:二分,可行,题目,mid,这个,答案,小结,我们
From: https://www.cnblogs.com/helloworld-congqiancongqian/p/17399850.html

相关文章

  • 考试与小结——cqbz周考2
    考试与小结——cqbz周考2心路历程:1.机器人走方格第一题:模拟呗,暴力呗,有什么好说的然后70/100?错误的原因在于,我在枚举操作的时候,我给的判断是,如果现在是最后一个操作,且没有到过终点,就false,但很有可能他下一步就可以到终点,所以改成现在是最后一个+1的操作100/100焯2.多米诺......
  • 考试与小结——cqbz周考1总结
    考试与小结——cqbz周考1总结说说心路历程1.见到题时,第一题,哇,感觉好简单,模拟就行了确实是模拟,但是呢,细节处理没有到位,特别是最后一排文字的输出,多个空格少个空格的0/100,GG2.覆盖:见到这个题时脑子很混乱没有答题的思路和方向,现在知道这种题就是找规律构建函数有些经验了,知道......
  • 如何使用Python实现二分查找算法
    二分查找算法是一种常用的搜索算法,其时间复杂度为O(logn),可以快速地从有序数组中找出目标元素。在本篇文章中,我们将学习如何使用Python实现二分查找算法。二分查找算法的原理很简单:首先确定数组的中间位置,然后将目标元素与中间元素进行比较。如果目标元素小于中间元素,则在数组的左......
  • c++ class类bfs模板题目
    题目网址:走迷宫-题目-Liuser'sOJ(cpolar.cn)原本代码(bfs广度优先搜索):#include<bits/stdc++.h>usingnamespacestd;constintN=50;intn,m;intsx,sy;chara[N][N];intb[N][N];boolvis[N][N];intdx[]={1,0,-1,0};intdy[]={0,-1,0,1};structnode{i......
  • 第二次博客:PTA题目集4-5总结
    第二次博客:PTA题目集4-5总结 前言:有了前三次的菜单系列的洗礼,我对这两次的点菜还是有一定的信心的。老师也说期中考试会于点菜系列有一定的联系。但是事实告诉你永远不要试图揣测蔡老师的心思。先说期中考试:题目概述:总共4题,(和点菜没有半毛钱关系)不过总体来说......
  • 力扣题目两两交换链表中的节点
    题目:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)示例1:解题思路对于这道题我们可以为原链表增加一个哨兵卫,然后创建三个指针,最前面的指针用于判断是否还存在需要交换的节点,后面的两个节点用于交换......
  • 【牛客小白72】E 二分答案
    https://ac.nowcoder.com/acm/contest/56825/E题意给你\(10^{10}\)个数(数组an个数,数组bm个数,数是a*b的集合),有\(Q\)(Q为常数)个询问,每次问你第\(x\)小的数是多少思路最暴力的思路肯定是把所有数放在一起,然后排序。易知时间复杂度为\(nlogn(n=1e10)\),会超时。继续思......
  • 【二分查找】LeetCode 74. 搜索二维矩阵思路
    题目链接74.搜索二维矩阵思路思路因为矩阵中每行都按升序排列,且每行的第一个整数大于前一行的最后一个整数。所以整个矩阵其实就是一个大的升序的一维数组,可以使用二分查找的方法对“一维数组”进行搜索,只不过在获取元素的过程中需要进行一步一维索引到二维索引的映射。代码......
  • 【二分查找】LeetCode 162. 寻找峰值思路
    题目链接162.寻找峰值思路思路一个不严谨但是好理解的思路是:如果\(nums[mid]>nums[mid+1]\),那么\(nums[mid+1]\)肯定不是峰值,此时让\(right=mid\),从左边继续找峰值。反之则\(nums[mid]\)肯定不为峰值,让\(left=mid+1\)。代码classSolution{public......
  • 【数组01】二分查找&移除元素
    TableofContents二分查找704.二分查找35.搜索插入位置34.在排序数组中查找元素的第一个和最后一个位置69.x的平方根367.有效完全平方数移除元素27.移除元素26.删除排序数组中的重复项283.移动零844.比较含退格的字符串977.有序数组的平方Solutions7......