▎前置技能
▎前言
想必你已经学会了二分,但是你真的知道二分查找和二分答案的区别吗?
▎二分
☞『二分查找定义』
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。(copy自百度)
说白了就是用来查找一个元素是否存在。
☞『二分答案定义』
这个在网上没有一个官方的定义,根据小编的理解就是在一个问题不知道答案的情况下需要假设答案来带入看看对不对,而二分正是假设答案的利器。
☞『二分查找和二分答案的区别』
正如上所述,二分查找侧重于查找一个元素是否存在,而二分答案则侧重于找到答案。
▎二分答案例题
二分查找想必你已经很熟练了,那么二分答案你真的熟吗?废话不多说,直接上题:
1247:河中跳房子
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 2261 通过数: 1005
【题目描述】
每年奶牛们都要举办各种特殊版本的跳房子比赛,包括在河里从一个岩石跳到另一个岩石。这项激动人心的活动在一条长长的笔直河道中进行,在起点和离起点L远 (1 ≤ L≤ 1,000,000,000) 的终点处均有一个岩石。在起点和终点之间,有N (0 ≤ N ≤ 50,000) 个岩石,每个岩石与起点的距离分别为Di (0 < Di < L)。
在比赛过程中,奶牛轮流从起点出发,尝试到达终点,每一步只能从一个岩石跳到另一个岩石。当然,实力不济的奶牛是没有办法完成目标的。
农夫约翰为他的奶牛们感到自豪并且年年都观看了这项比赛。但随着时间的推移,看着其他农夫的胆小奶牛们在相距很近的岩石之间缓慢前行,他感到非常厌烦。他计划移走一些岩石,使得从起点到终点的过程中,最短的跳跃距离最长。他可以移走除起点和终点外的至多M (0 ≤ M ≤ N) 个岩石。
请帮助约翰确定移走这些岩石后,最长可能的最短跳跃距离是多少?
【输入】
第一行包含三个整数L, N, M,相邻两个整数之间用单个空格隔开。
接下来N行,每行一个整数,表示每个岩石与起点的距离。岩石按与起点距离从近到远给出,且不会有两个岩石出现在同一个位置。
【输出】
一个整数,最长可能的最短跳跃距离。
【输入样例】
25 5 2 2 11 14 17 21
【输出样例】
4
【提示】
在移除位于2和14的两个岩石之后,最短跳跃距离为4(从17到21或从21到25)。
【来源】
这道题如果事先没有学习过分治,那么就很难下手,因为这道题的答案不好正面求。
那么我们不妨使用侧面求解,也就是暴力枚举答案,套进去看看对不对。
但是这样太慢了,我们可以采取二分的方法优化。
这就是二分答案,代码如下:
1 #include<iostream> 2 using namespace std; 3 int L,N,M,a[60000],l,r,x; 4 int love(int mid) 5 { 6 int cnt=0,lx=0,i; 7 for(i=1;i<=N;i++) 8 { 9 if(a[i]-a[lx]<=mid) cnt++; 10 else lx=i; 11 } 12 return cnt; 13 } 14 int main() 15 { 16 cin>>L>>N>>M; 17 for(int i=1;i<=N;i++) 18 cin>>a[i]; 19 N++; 20 a[N]=L; 21 l=0;r=L; 22 while(l<=r) 23 { 24 int mid=(l+r)/2; 25 if(love(mid)>M) r=mid-1; 26 else l=mid+1; 27 } 28 cout<<l; 29 }