• 【刷题】【二分搜索】(1)


    模板

    找出最左边的一个,最右边的一个,和长度

    注意找左位置时要判断:

    1>不可以是字串结尾,不然为0或为空

    2>不可以不等于key

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    int n,m;
    const int N=100003;
    int d[N];
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&d[i]);
        
        int x;
        while(m--)
        {
            scanf("%d",&x);
            int pos1=lower_bound(d+1,d+n+1,x)-d;
            if(pos1>n || d[pos1]!=x)
            {
                printf("-1 -1 -1
    ");
                continue;
            }
            int pos2=upper_bound(d+pos1+1,d+n+1,x)-d;
            
            printf("%d %d %d
    ",pos1,pos2-1,pos2-pos1);
        }
         
        return 0;
    } 

    例题1

    阿弥陀佛数数游戏

    N个数字(N<=500000),K(K<=500000)个问题,

    每个问题询问从L到R中,到底有多少个数字是KEY值?

    数据都是int可以存储的

    神仙思路:

    题目虽然有两个关键字,但是只求第一个关键字相等的情况,所以可以直接sort

    sort以后找到相等区间,再去搞第二关键字就好

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    int n,k;
    const int N=500003;
    struct node
    { 
        int v,id;
        bool operator < (const node & o) const
        { return v==o.v? id<o.id :v<o.v; }
    }d[N];
    
    int main()
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
            scanf("%d",&d[i].v ),d[i].id =i;
        sort(d+1,d+n+1);
        
        int l,r;
        node t;
        while(k--)
        {
            scanf("%d%d%d",&l,&r,&t.v );
            t.id =l;
            int pos1=lower_bound(d+1,d+n+1,t)-d;
            if(pos1>n || d[pos1].v !=t.v || d[pos1].id >r)
                printf("0
    ");
            else
            {
                t.id =r;
                int pos2=upper_bound(d+pos1,d+n+1,t)-d;
                printf("%d
    ",pos2-pos1);
            }
        }
        
        return 0;
    }

    例题2

    晒衣服

    1>贪心

    众所周知,堆比sort快(除了我)

    #include<cstdio>
    #include<cstdlib>
    #include<queue>
    using namespace std;
    priority_queue <int> q;
    int n,a,b;
    int main()
    {
        scanf("%d%d%d",&n,&a,&b);
        int x;
        for(int i=1;i<=n;i++)
            scanf("%d",&x),q.push(x); 
        
        int t=0;
        while(q.top() > a*t)
        {
            x=q.top() -b;
            q.pop() ;
            t++;
            q.push(x); 
        }
        printf("%d
    ",t);
        return 0;
    }

    2>二分搜索答案

    二分快速确认答案范围

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int n,a,b;
    const int N=500000;
    int d[N+3];
    bool check(int tm)
    {
        int cnt=tm;
        for(int i=n;i;i--)
        {
            if(d[i]<=tm*a)
                return true;
            int t=d[i]-tm*a;
            int nd=(ceil(t/(b*1.0)));
            if(nd>cnt) return false;
            else cnt-=nd;
        }
        return true;
    }
    int main()
    {
        scanf("%d%d%d",&n,&a,&b);
        for(int i=1;i<=n;i++) scanf("%d",&d[i]);
        sort(d+1,d+n+1);
        
        int l=1,r=d[n]/a+1;
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(check(mid)) r=mid;
            else l=mid+1;
        }
        printf("%d
    ",l);
        
        return 0;
    } 

    例题3

    穿越七彩虹

    小数的二分

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    double h,ed;
    double x[10],r[10];
    struct node
    {
        double l,r;
        bool operator < (const node & o) const
        {
            if(l==o.l) return r<o.r;
            else return l<o.l;
        } 
    }d[10];
    bool check(double ch)
    {
        for(int i=1;i<=7;i++)
        {
            double tt=sqrt((r[i]+ch)*(r[i]+ch) -h*h);
            d[i].l =x[i]-tt;
            d[i].r =x[i]+tt;
        }
        sort(d+1,d+8);
        
        double rr=d[1].r ;
        if(d[1].l >0) return false;
        for(int i=2;i<=7;i++)
        {
            if(d[i].l >= rr) return rr>=ed;
            rr=max(d[i].r ,rr);
        }
        return rr>=ed;
    }
    int main()
    {
        scanf("%lf%lf",&h,&ed);
        for(int i=1;i<=7;i++)
            scanf("%lf%lf",&x[i],&r[i]);
        
        double l=0,r=ed;
        int cnt=400;
        while(r-l>=0.0001 && cnt--)
        {
            double mid=(l+r)/2;
            if(check(mid)) r=mid;
            else l=mid;
        }
        
        printf("%.2lf",l);//四舍五入输出两位小数
        return 0;
    }

    例题4

    矩形分割

    平面上有一个大矩形,其左下角坐标(0,0),右上角坐标(R,R)。大矩形内部包含一些小矩形,小矩形都平行于坐标轴且互不重叠。所有矩形的顶点都是整点。要求画一根平行于y轴的直线x=k(k是整数) ,使得这些小矩形落在直线左边的面积必须大于等于落在右边的面积,且两边面积之差最小。并且,要使得大矩形在直线左边的的面积尽可能大。注意:若直线穿过一个小矩形,将会把它切成两个部分,分属左右两侧。

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    int r,n;
    const int R=1000003;//注意:我将面积落在偏右节点上 
    long long cf[R],sum[R];//cf是i项减去i-1项//sum是前i项的面积之和 ,则sum的有效部分是[2,r],第一项面积为0 
    
    int main()
    {
        scanf("%d%d",&r,&n);
        int x,y,w,h;
        while(n--)
        {
            scanf("%d%d%d%d",&x,&y,&w,&h);
            cf[x+1]+=h,cf[x+w+1]-=h; 
        }
        
        long long nw=0;//差分序列前i项的和 
        for(int i=1;i<=r;i++)
        {
            nw+=cf[i];
            sum[i]=sum[i-1]+nw;
        }
        
        long long mid=sum[r]-(sum[r]>>1);
        
         int pos=lower_bound(sum,sum+r+1,mid)-sum;
        while(pos<r && sum[pos]==sum[pos+1]) pos++; 
        
        int pos2=upper_bound(sum+1,sum+r+1,mid)-sum;
        if(pos2 && sum[pos2-1]>=mid) pos2--; //注意:这两段其实是不一样的,第二段中的sum[pos2]虽然一定大于了mid,是最小差值,但是不一定是最后一个最小差值 
        //再加上一个向后寻找就好了 
        printf("%d
    ",pos);
        
        return 0;
    } 

    例题5

    有道搜索框

    //注意呀:字符串可以都看作数
    //只是比大小是左对齐形式罢了
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int n,q;
    const int N=10003;
    string s[N],ask;
    int pos;
    int main()
    {
        cin>>n;//cin和scanf不要混用
        for(int i=0;i<n;i++)
            cin>>s[i];
        sort(s,s+n);
        n=unique(s,s+n)-s;//神仙去重 
    
        cin>>q; 
        while(q--)
        {
            cin>>ask;
            int pos1=lower_bound(s,s+n,ask)-s;
            
            pos=ask.length() ;
            ask[pos-1]++;
            int pos2=lower_bound(s+pos1,s+n,ask)-s;
            
            if(pos1==pos2)//神仙判ask是否为s[pos1]的前缀 
            {
                ask[pos-1]--;
                cout<<ask<<endl;
            }
            else
            {
                for(int i=0;i<8 && pos1+i<pos2;i++)
                    cout<<s[pos1+i]<<" ";
                cout<<endl;
            }
        }   
        return 0;
    }
  • 相关阅读:
    Hadoop源码分析1: 客户端提交JOB
    《分布式系统原理与范型》习题答案 6.一致性和复制
    《分布式系统原理与范型》习题答案 5.同步
    《分布式系统原理与范型》习题答案 4.命名
    《分布式系统原理与范型》习题答案 3.进程
    《分布式系统原理与范型》习题答案 2.通信
    《分布式系统原理与范型》习题答案 1.绪论
    计算机基础知识面试
    机器学习面试题
    计算机网络面试题
  • 原文地址:https://www.cnblogs.com/xwww666666/p/11395899.html
Copyright © 2020-2023  润新知