CUGBACM/ICPCGROUP二分查找算法CUGBACM/ICPCGROUP简单定义:在一个单调有序的集合中查找元素,每次将集合分为左右两部分,判断解在哪个部分中并调整集合上下界,重复直到找到目标元素。时间复杂度:O(logn),优于直接顺序查找O(n)二分查找算法CUGBACM/ICPCGROUP例子:CUGBACM/ICPCGROUP//x:待查找的元素,n:数组集合大小,num数组单调递增intlow=0,high=n,mid,res=-1;//low:集合下界high:集合上节while(low=high){mid=(low+high)/2;//mid:将集合分割为两部分if(num[mid]==x)//查找到符合元素x{res=mid;break;}elseif(num[mid]x)//x在右边部分,调整集合下界low=mid+1;else//x在左边部分,调整集合上界high=mid-1;}//若未找到x,则res=-1参考程序CUGBACM/ICPCGROUP查找连续函数的写法//x:待查找的值,Caculate():所要查找的函数,在这里单调递增//需保证查找的值在区间范围内doublelow=“区间下界”,high=“区间上界”,mid;while(high-low1.0e-6){mid=(high+low)/2;if(Caculate(mid)x)low=mid;elsehigh=mid;}CUGBACM/ICPCGROUP常见拓展对于某些问题,如果答案具有特定的范围,并且验证答案是否成立的函数具有单调性。则可以在范围内对答案进行二分验证,从而快速确定答案。CUGBACM/ICPCGROUP例子:HOJ2651PIE题目大意:有f+1个人分n块披萨,每个人要求分得的面积一样,且披萨只能被切开而不能重新组合,求每个人能分到的最大面积v。分析:对于每个确定的v,可以计算出最多能满足的人数p。因此得到一个单调递减的函数关系,并且v的范围也可以确定为0~max(size(i)),i=1...n。CUGBACM/ICPCGROUPx轴——每个人分到的面积vy轴——对应可分最大人数p对于第一组样例——图中红点所对应的v值即为最优解,二分查找满足p=4时v的最大值即可得到答案CUGBACM/ICPCGROUP//由于精度差问题,考虑先将面积*1000000转化为整数来二分longlongres,mid;while(low=high){mid=(high+low)/2;if(judge(mid)){low=mid+1;res=mid;//最后结果为res}else{high=mid-1;}}核心代码booljudge(longlongmid){longlongp=0;for(inti=0;in;++i){p+=size[i]/mid;}returnp=f;}CUGBACM/ICPCGROUP推荐题目Poj3273,1434Hdu2141,2899,1969Coj1080,1216,1048CUGBACM/ICPCGROUP当需要求某凸性或凹形函数的极值,通过函数本身表达式并不容易求解时,就可以用三分法不断逼近求解。三分法CUGBACM/ICPCGROUP类似二分的定义Left和Rightmid=(Left+Right)/2midmid=(mid+Right)/2;如果mid靠近极值点,则Right=midmid;否则(即midmid靠近极值点),则Left=mid;三分法CUGBACM/ICPCGROUP例子:ZOJ3203LightBulb=3203如图,人左右走动,求影子L的最长长度。根据图,很容易发现当灯,人的头部和墙角成一条直线时(假设此时人站在A点),此时的长度是影子全在地上的最长长度。当人再向右走时,影子开始投影到墙上,当人贴着墙,影子长度即为人的高度。所以当人从A点走到墙,函数是先递增再递减,为凸性函数,所以我们可以用三分法来求解。CUGBACM/ICPCGROUPdoublemid,midmid;while(low+epshigh){mid=(low+high)/2;midmid=(mid+high)/2;doublecmid=cal(mid);doublecmidmid=cal(midmid);if(cmidcmidmid)high=midmid;elselow=mid;}核心代码doublecal(doublex){return(h*D-H*x)/(D-x)+x;//这里放要求的函数;}CUGBACM/ICPCGROUP对于求解一些实际问题,当公式难以推导出来时,二分、三分法可以较为精确地求解出一些临界值,且效率也是令人满意的。灵活应用这些方法对解题会很有帮助。总结