ACM选修课6 二分法与构造矩阵

二分法

lower_bound()返回值是一个迭代器,返回指向大于key的第一个值的位置
使用:lower_bound(a,a+8,key)-a

upper_bound()返回值是一个迭代器,返回指向大于等于key的第一个值的位置
使用:upper_bound(a,a+8,key)-a

例题

二分查找

#include <bits/stdc++.h>
using namespace std;
int a[1000010];
int main()
{
    int n,x;
    while(cin>>n>>x)
    {
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        printf("%d\n",lower_bound(a,a+n,x)-a);
    }
    return 0;
}

小清新的二倍问题加强版-二分-桶排

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    scanf("%d",&n);
    for(int a=0; a<n; a++)
    {
        int x[100500]= {0},m,res=0,i;
        for(i=1;; i++)
        {
            scanf("%d",&m);
            if(m==0)
                break;
            else
                x[m]=1;
        }
        for(int j=1; j<50250; j++)
        {
            if(x[j]==1&&x[j*2]==1)
                res++;
        }
        printf("%d\n",res);
    }
    return 0;
}

小清新的二分查找之旅

#include <bits/stdc++.h>
using namespace std;
int x[1000100];
int main()
{
    int n,q;
    while(scanf("%d%d",&n,&q)!=-1)
    {
        int y;
        for(int i=1; i<=n; i++)
            scanf("%d",&x[i]);
        for(int i=1; i<=q; i++)
        {
            int res;
            scanf("%d",&y);
            res=upper_bound(x+1,x+1+n,y)-x-1;
            if(x[res]==y)
                printf("no\n");
            else
                printf("YES\n");
        }
    }
    return 0;
}

小清新的函数坐标-二分

#include <bits/stdc++.h>
using namespace std;
double f(double x);
int main()
{
    double y;
    while(scanf("%lf",&y)!=-1)
    {
        double l=-20.0,r=20.0,m,res;
        while(l<r)
        {
            m=(l+r)/2.0;
            if(r-l<1e-8)
                break;
            if(f(m)>y)
                r=m;
            else
                l=m;
        }
        printf("%.4lf\n",m);
    }
    return 0;
}
double f(double x)
{
    double res;
    res=0.0001* pow(x,5) + 0.003 *pow(x,3) + 0.5 *x - 3.0;
    return res;
}

小清新切绳子-二分

#include <bits/stdc++.h>

using namespace std;

int check(int m);

int x[100000],n,k;
int main()
{
    while(scanf("%d%d",&n,&k)!=-1)
    {
        int res=0;
        for(int i=1; i<=n; i++)
            scanf("%d",&x[i]);
        int r=x[1],l=0,m;
        for(int i=2; i<=n; i++)
            if(r<x[i])
                r=x[i];
        while(l<=r)
        {
            m=(l+r)/2;
            if(check(m)==1)
            {
                res=m;
                l=m+1;
            }
            else
                r=m-1;
        }
        printf("%d\n",res);
    }
    return 0;
}

int check(int m)
{
    int res=0;
    for(int i=1; i<=n; i++)
        res=res+x[i]/m;
    if(res>=k)
        return 1;
    else
        return 0;
}

成绩查询

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n,k,min_b,max_b;
    scanf("%d",&n);
    double  a[100005],minl,maxr;
    for(int i=0; i<n; i++)
        scanf("%lf",&a[i]);
    sort(a,a+n);
    while(~scanf("%lf%lf",&minl,&maxr))
    {
        min_b=lower_bound(a,a+n,minl)-a;
        max_b=upper_bound(a,a+n,maxr)-a;
        k=max_b-min_b;
        printf("%d\n",k);
    }
    return 0;
}

这也是裸的找

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n,k;
    while(~scanf("%d%d",&n,&k))
    {
        int r=1,l=n,mid,res=0;
        while(r<=l)
        {
            res++;
            mid=(r+l)/2;
            if(mid==k)
                break;
            if(mid<k)
                r=mid+1;
            else
                l=mid-1;
        }
        printf("%d\n",res);
    }
    return 0;
}

数列分段-二分

#include <bits/stdc++.h>
using namespace std;
int arr[100002];
int n, m;
int lef, rig, mid;
int tu, ts;
bool judge(int mid)//用来判别是否每一段都可以小于mid
{
    for (int i=1;i<=n;i++)
    {
        if (tu+arr[i]<=mid)//如果还是小于mid,就继续加上去
            tu+=arr[i];
        else//否则就开启另一段,ts加一,并且设置tu为当前的数字
        {
            ts+=1;
            tu=arr[i];
        }
    }
    return ts>=m;
}
int main()
{
    cin>>n>>m;
    for (int i = 1; i <= n; i++)
    {
        cin>>arr[i];
        rig+=arr[i];
        lef=lef>arr[i]?lef : arr[i];
    }
    while(lef<=rig)
    {
        mid =(lef +rig)/2;
        ts=tu=0;
        if(judge(mid))//如果最后的ts是大于m的话,说明mid太小了,需要lef往右移
            lef=mid+1;
        else//否则就是mid太大了
            rig=mid-1;
    }
    cout<<lef<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_46126537/article/details/105867620