二分查找

     二分查找,思想很简单,在很多书中都有介绍,如果查找的元素一定存在序列中,实现起来简单一些。但是有的时候元素并不存在,就要根据题目中的要求,去判断是去求上界还是去求下界。以下内容参考此博客,这个博客讲的很不错,参考了一下。以下所有的题目,都是递增序列。

      HDU 4217 Data Structure? 题目大意就是让把第几大的元素找到,然后把这个元素删去,算出删去元素的和。这个题的一种解法是用树状数组记录,然后中间用到二分,这个时候因为getsum(i)存的是前i个数有有几个元素,所以第一个等于关键值的i,才是要求的结果。最后str是我们要求的结果。

关键代码:

1 while(str < end)//必须小于,小于等于会超时
2 {
3     mid = (str+end)/2;
4     midsum = getsum(mid);//树状数组的求和
5     if(midsum < a)//a是关键值
6         str = mid+1;
7 else
8 end = mid;//必须这么写
9 }

      HDU 4151The Special Number 很早之前做的一个题了,这个二分写的更加纠结。。。暴力预处理出所有的结果,找寻第一个比a小的元素,感觉既不是求上界也不是求下界。这个题看的题解,二分写的很巧妙。key为最后的结果,而且必须这样写,其实我也不太懂为什么这样写。。。

 1 while(str <= end)//必须这么写。。。不加等号会WA。。
 2 {
 3     mid = str + (end - str)/2;
 4     if(p[mid] < a)
 5     {
 6         key = mid;//key记录第一个比a小的值
 7         str = mid+1;
 8     }
 9     else
10     {
11         end = mid-1;//必须-1,不然也会超时。。
12     }
13 }

  今天又看这个题,这就是求上界啊,只要最后讨论下,是否与关键值相等即可。

 1 while(str < end)
 2 {
 3     mid = (str + end + 1)/2;
 4     if(p[mid] > a)
 5     {
 6         end = mid - 1;
 7     }
 8     else
 9     {
10         str = mid;
11     }
12 }
13 if(p[end] == a)
14     printf("%d\n",end - 1);
15 else
16     printf("%d\n",end);

二分求上界最后一次出现的位置,如果不存在,就是左边第一个小于a的元素。end是取得的结果。

 1 while(str < end)
 2 {
 3     mid = (str + end + 1)/2;//注意。。。+1
 4     if(mid > a)
 5     {
 6         end = mid - 1;//注意。。
 7     }
 8     else
 9     {
10         str = mid;
11     }
12 }

二分求下界。str为最后的结果。第一个出现的和a相等的元素,如果不存在就是右边,第一个比a大的元素。

 1 while(str < end)
 2 {
 3     mid = (str + end)/2;
 4     if(p[mid] < a)
 5     {
 6         str = mid + 1;
 7     }
 8     else
 9     {
10         end = mid;
11     }
12 }
posted @ 2012-08-05 20:35  Naix_x  阅读(218)  评论(0编辑  收藏  举报