算法描述》关于二分的两三事

  关于二分

   二分,是一种流氓算法,这种方法适用于直接算(猜、蒙、试)答案,然后直接得出最优解,

  这一方法,对于可以轻易证明答案是否可行(o(n)、o(1))的题目有奇效,

  (在NOIP2015考试的时候出了这么一道题,放倒一推蒟蒻(包括我))

  二分的使用条件

  1.如上文所说,对于轻易证明答案是否可行的题目有奇效,来一道解决一道,对于子问题有这一性质的,也可以同样用这种方法解决,奇效。(以下有相关内容)

  2.对于所查询区间值为递增或递减的问题来说,这也是一种极其可行的方法,

  关于写法以及STL若干事

  每一位神犇几乎都有自己有个性的二分写法,因为这个东西可以有所差异的地方实在太多,但究其本身,还都是同一种道理。

  1.关于<algorithm>中,STL的写法

  在c++的库函数里,有两个二分函数,分别叫upper_bound和lower_bound。

  

  upper_bound

  这一库函数的定义是:在当前传来的非降序列两个地址中间,return第一个大于当前传来的值的地址。

  使用格式为:upper_bound(a+1,a+n+1,num);

  其中a数组为我们所要查询的非降数组,而1、n+1分别为我们要查找的区间地址(也即数组变量名+查询的开始 / 结束位置),num为我们所要查询的值。

  具体库函数代码如下

 1 int upper_bound(int *array, int size, int key)
 2 {
 3     int first = 0, len = size-1;
 4     int half, middle;
 5
 6     while(len > 0){
 7         half = len >> 1;
 8         middle = first + half;
 9         if(array[middle] > key)     //中位数大于key,在包含last的左半边序列中查找。
10             len = half;
11         else{
12             first = middle + 1;    //中位数小于等于key,在右半边序列中查找。
13             len = len - half - 1;
14         }
15     }
16     return first;
17 }

  lower_bound

  这一库函数的定义是:在当前传来的非降序列两个地址间,return第一个大于等于当前传来的值的地址。

  使用格式:lower_bound(a+1,a+n+1,num);

  各数组意义的定义和上面的基本一致

  库函数代码如下

 1 int lower_bound(int *array, int size, int key)
 2 {
 3     int first = 0, middle;
 4     int half, len;
 5     len = size;
 6
 7     while(len > 0) {
 8         half = len >> 1;
 9         middle = first + half;
10         if(array[middle] < key) {
11             first = middle + 1;
12             len = len-half-1;       //在右边子序列中查找
13         }
14         else
15             len = half;            //在左边子序列(包含middle)中查找
16     }
17     return first;
18 }

  2.关于个人代码习惯

  这里有两种,分别是preyW和szl两神犇的不同二分写法习惯,在这里供参考

 1 int prey_BS(int l, int r, int key)
 2 {
 3     while( l < r - 1 )
 4     {
 5         m = (l+r)>>1;
 6         if(a[m] < key)
 7             l = m + 1;
 8         else
 9             r = m;
10     }
11     return l;
12 }
 1 int zl_BS(int l, int r, int key)
 2 {
 3     int ans;
 4     while(l < = r)
 5     {
 6         m = (l + r)>>1;
 7         if(a[m] < key)
 8             l = middle + 1;
 9         else{
10             r = m - 1;
11             ans = r;
12         }
13     }
14     return ans;
15 }

  这两种方法可能和神犇亲手写的有出入,不过大概就是这样

  总的来说,二分还是一种解题利器,如果对于写法不够明确的看官,可以用以上的STL以及神犇写法来代替自己原本的,可能效果会更好

  然后例题就是全部openjudge以及codevs的二分题

  祝大家刷的开心

时间: 2024-10-24 23:51:16

算法描述》关于二分的两三事的相关文章

HDU 4004 The Frog&#39;s Games(基本算法-贪心,搜索-二分)

The Frog's Games Problem Description The annual Games in frogs' kingdom started again. The most famous game is the Ironfrog Triathlon. One test in the Ironfrog Triathlon is jumping. This project requires the frog athletes to jump over the river. The

【算法拾遗】二分查找递归非递归实现

转载请注明出处:http://blog.csdn.net/ns_code/article/details/33747953 本篇博文没太多要说的,二分查找很简单,也是常见常考的查找算法,以下是递归非递归的实现. 非递归实现: /* 非递归实现,返回对应的序号 */ int BinarySearch(int *arr,int len,int key) { if(arr==NULL || len<1) return -1; int low = 0; int high = len-1; while(l

算法——基础篇——二分查找

     二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表.     首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功:否则利用中间位置记录将表分成前.后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表.重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功

标准的Base64算法描述

作者:zhanhailiang 日期:2014-12-19 算法描述: Base64要求把每三个8Bit的字节转换为四个6Bit的字节(38 = 46 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3. 第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一个目标字符. 然后将第一个字符与0x03(00000011)进行与(&)操作并左移4位,接着第二个字符右移4位与前者相或(|)

鸽巢排序算法描述和代码举例

//鸽巢排序//适用条件:所有取值的范围确定,并且在这个范围内个元素的出现频率较高.//算法描述:为取值范围内的各个可能取到的元素建巢用一维数组表示,巢中//    巢中存放该元素出现的个数(通过遍历待排序数统计存入).按照巢的//    顺序和巢中元素个数列出该有序序列.//算法空间复杂度为:S(1)时间复杂度为:O(n). //例:20个非负数,其中每个数的取值范围为1~9. #include<iostream>#include<time.h>using namespace s

Python 迭代器&amp;生成器,装饰器,递归,算法基础:二分查找、二维数组转换,正则表达式,作业:计算器开发

本节大纲 迭代器&生成器 装饰器  基本装饰器 多参数装饰器 递归 算法基础:二分查找.二维数组转换 正则表达式 常用模块学习 作业:计算器开发 实现加减乘除及拓号优先级解析 用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式,运算后得出结果,结果必须与真实的计算器所得出的结果一致 迭代器&

挖掘相关规则的算法描述

Mining Assocaition rule algrothm(挖掘相关规则的算法) 此算法中有两个关键参数,coverage(表示预测正确的案例个数,此参数用来筛选哪些实例个数大于或等于这个值得相关规则) accuracy(表示预测数据的精确度,此参数实际上是满足相关规则的实例的个数/满足规则前部分条件的实例个数) A  找到满足coverage参数的所有项数的规则集合算法描述 把1赋给变量k 找到所有的满足coverage数量的k项规则集合,并且把它们保存到哈希表#1中 while 发现一

十大经典排序算法的算法描述和代码实现

这里详细讲解了十大经典算法的分类,例如交换排序.插入排序.选择排序等比较类排序,以及计数排序.桶排序和基数排序的非比较类排序,分析了各种排序算法的复杂度和稳定性,还有JAVA代码的详细实现.对冒泡排序.插入排序.选择排序和堆排序等十种算法进行了详细的思想总结. 一.算法概述 1.算法分类 十种常见排序算法可以分为两大类:(1)比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn)因此也称为非线性时间比较类排序.(2)非比较类排序:不通过比较元素间的相对次序,它可以突

插入排序的算法描述和分析

插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法. 它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入.插入排序在实现上, 通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中, 需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间. 时间复杂度:最佳为o(n):因为如果是已经排序好的序列话,它每次只需和前面已排序好的序列比较一次,总共比较n次,也是可以通过flag实现的,然后最差时