二分查找的应用

Posted Lewin的成长之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分查找的应用相关的知识,希望对你有一定的参考价值。

当前浏览器不支持播放音乐或语音,请在微信或其他浏览器中播放 二分查找的应用(一) 二分查找的应用:

一:解具有单调性的方程:通过单调性和函数值的大小,左右移动left和right,但是要注意精度的取值,一般来说eps取1e-6就够了,但是有些题目可能会WA,这时就需要自己慢慢调整eps来试了,比如下面的这一题eps就过不了,然后我试了eps=1e-5,也WA了,然后取eps=1e-9就AC了.

二分查找的应用(一)


Accepted code:

 
   
   
 
  1. #include <iostream>

  2. #include<cstdio>

  3. #include<cmath>

  4. using namespace std;

  5. const double eps=1e-9;

  6. const double e=2.7182818284590452354;

  7. int p,q,r,s,t,u;

  8. double f(double x)

  9. {

  10.    return p * pow(e,-x) + q * sin(x) + r * cos(x) + s * tan(x) + t * x *x + u ;

  11. }

  12. int main()

  13. {

  14.    while(~scanf("%d%d%d%d%d%d",&p,&q,&r,&s,&t,&u))

  15.    {

  16.        double mid=-1,left=0,right=1;

  17.        while(right-left>eps)

  18.        {

  19.            mid=left+(right-left)/2.0;

  20.            if(f(mid)>0)

  21.            {

  22.                left=mid;

  23.            }

  24.            else

  25.            {

  26.                right=mid;

  27.            }

  28.        }

  29.        if(fabs(f(mid))<1e-7)

  30.            printf("%.4f ",mid);

  31.        else

  32.            printf("No solution ");

  33.    }

  34. }


二.最小化最大值,或者最大化最小值:

(来自https://www.cnblogs.com/xiaowuga/p/8609943.html) 1.最小值最大化:我们假设x为最大的最小值,那么x-1是满足条件的,但他并不满足最大,x+1是不满足条件的,假设我们左边界是L,右边界是R,我们二分一个答案ans,ans为最后一个满足条件的数,我们是不是可以类比二分搜索(一)中的lastlessequal()或者lastless()这个问题和这两者是差不多的。 2.最大值最小化:我们假设x为最小的最大值,那么x-1是不满足条件的,x+1是满足条件的,但他不满足最小,假设我们左边界是L,右边界是R,我们二分一个答案ans,ans为第一个满足条件的数,我们是不是可以类比二分搜索(一)中的lowerbound()或者upper_bound()这个问题和这两者是差不多的。

我的理解:

最大化最小值:ans的范围是(x1,x2],求x2 最小化最大值:ans的范围是[x1,x2),求x1

下面看题:

Pie(POJ3122)

My birthday is coming up and traditionally I'm serving pie. Not just one pie, no, I have a number N of them, of various tastes and of various sizes. F of my friends are coming to my party and each of them gets a piece of pie. This should be one piece of one pie, not several small pieces since that looks messy. This piece can be one whole pie though.

My friends are very annoying and if one of them gets a bigger piece than the others, they start complaining. Therefore all of them should get equally sized (but not necessarily equally shaped) pieces, even if this leads to some pie getting spoiled (which is better than spoiling the party). Of course, I want a piece of pie for myself too, and that piece should also be of the same size.

What is the largest possible piece size all of us can get? All the pies are cylindrical in shape and they all have the same height 1, but the radii of the pies can be different.

Input

One line with a positive integer: the number of test cases. Then for each test case: One line with two integers N and F with 1 ≤ N, F ≤ 10 000: the number of pies and the number of friends. One line with N integers ri with 1 ≤ ri ≤ 10 000: the radii of the pies.

Output

For each test case, output one line with the largest possible volume V such that me and my friends can all get a pie piece of size V. The answer should be given as a floating point number with an absolute error of at most 10−3.

Sample Input

3 3 3 4 3 3 1 24 5 10 5 1 4 2 3 4 5 6 5 4 2

Sample Output

25.1327 3.1416 50.2655


这题是一题典型的最大化最小值,题目是寒假积分赛的题目,按着二分的套路做就行了.但是真的是很难AC,我做这题至少WA了10次,一开始在调eps,后来发现怎么调都是错的.然后开始怀疑输入输出的问题,把scanf和print都换成cin,cout,后来发现还是不行.于是乎,我开始怀疑后台数据,所以我就直接去了POJ提交,没想到还是错.实在是做不下去了,于是我就打开了讨论区(答案区),发现有个人评论说把%lf改成%f就能AC了,我试了一下,看到结果,心里一万个草泥马在奔腾,血泪呀!不过这也说明对于double类型的输出%f和%lf是不一样的,以后要是WA得找不出错误,倒是可以往这个方向思考.

Accepted code:

 
   
   
 
  1. #include <cstdio>

  2. #include<cmath>

  3. using namespace std;

  4. const double PI = acos(-1.0);

  5. const double eps=1e-5;

  6. const int maxn=10005;

  7. double r[maxn];

  8. int n,f;

  9. bool judge(double ans)

  10. {

  11.    int num=0;

  12.    for(int i=0;i<n;i++)

  13.    {

  14.        num+=(int)(PI*r[i]*r[i]/ans);

  15.    }

  16.    return num>=f+1;

  17. }

  18. int main()

  19. {

  20.    int t;

  21.    scanf("%d",&t);

  22.    while(t--)

  23.    {

  24.        scanf("%d%d",&n,&f);

  25.        for(int i=0;i<n;i++)

  26.            scanf("%lf",&r[i]);

  27.       double left=0,right=0x3fffffff,mid;

  28.       while(right-left>eps)

  29.       {

  30.           mid=left+(right-left)/2.0;

  31.           if(judge(mid))

  32.               left=mid+eps;

  33.           else

  34.               right=mid-eps;

  35.       }

  36.       printf("%.4f ",mid);

  37.    }

  38. }


Aggressive cows(POJ2456)

Description

Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. The stalls are located along a straight line at positions x1,...,xN (0 <= xi <= 1,000,000,000).

His C (2 <= C <= N) cows don't like this barn layout and become aggressive towards each other once put into a stall. To prevent the cows from hurting each other, FJ want to assign the cows to the stalls, such that the minimum distance between any two of them is as large as possible. What is the largest minimum distance?

Input

  • Line 1: Two space-separated integers: N and C

  • Lines 2..N+1: Line i+1 contains an integer stall location, xi

Output

  • Line 1: One integer: the largest minimum distance

Sample Input

5 3 1 2 8 4 9

Sample Output

3


Accepted code:

 
   
   
 
  1. #include <iostream>

  2. #include<cstdio>

  3. #include<algorithm>

  4. using namespace std;

  5. const int maxn=100005;

  6. long long int x[maxn];

  7. int n,c;

  8. bool judge(long long int mid)

  9. {

  10.    int s=x[0];

  11.    long long int num=1;

  12.    for(int i=0;i<n;i++)

  13.    {

  14.        if(x[i]-mid>=s)

  15.        {

  16.            num++;

  17.            s=x[i];

  18.        }

  19.    }

  20.    return num>=c;

  21. }

  22. int main()

  23. {

  24.    while(~scanf("%d%d",&n,&c))

  25.    {

  26.        for(int i=0;i<n;i++)

  27.        {

  28.            scanf("%lld",&x[i]);

  29.        }

  30.        long long int left=0,right=1000000005,mid;

  31.        sort(x,x+n);

  32.        while(right>=left)

  33.        {

  34.            mid=left+(right-left)/2;

  35.            if(judge(mid))

  36.                left=mid+1;

  37.            else

  38.                right=mid-1;

  39.        }

  40.        mid=(left+right)/2;

  41.        printf("%lld ",mid);

  42.    }

  43. }


以上是关于二分查找的应用的主要内容,如果未能解决你的问题,请参考以下文章

查找2-二分查找

Task 04:数组二分查找

leetcode查找算法(顺序查找,二分法,斐波那契查找,插值查找,分块查找)

剑指offer53(二分的应用)

二分查找

二分查找及其应用总结