zoukankan      html  css  js  c++  java
  • 二分1

    二分题目中通常有暗示:

    最大值最小/最小值最大 (在最之间取平衡点)

    最靠近某个值(类似)

    最小的能满足条件的代价

    ***寻找题目中具备的单调性,运用二分解决问题

     聪明的质检员  https://www.luogu.org/problemnew/show/ P1314

    二分+前缀和(通常区间求值)
    通过判断呢,W越大,sum越小,单调性具备。
    看了题解,发现min1的初始值设定过小
    #include<iostream> #include<algorithm> #include<cstring> using namespace std; #define ll long long struct stone{ ll w,v; }st[200001]; ll n,m,s,min1=0x3f3f3f3f3f3f3f3f,max1=-1,mi=0x3f3f3f3f3f3f3f3f,sumw[200001],sumv[200010]; struct ma{ ll l,r; }q[200001]; int main() { cin>>n>>m>>s; for(int i=1;i<=n;i++) cin>>st[i].w>>st[i].v,mi=min(mi,st[i].w),max1=max(max1,st[i].w); for(int i=1;i<=m;i++) { ll l,r; cin>>q[i].l>>q[i].r; } ll left=mi-1,right=max1,mid; while(left<=right) 二分,列举W可能取值 { mid=(left+right)/2;
         memset(sumv,0,sizeof(sumv)),memset(sumw,0,sizeof(sumw)); 注意初始化
    for(int i=1;i<=n;i++)前缀和计算w的个数 if(st[i].w>=mid) sumw[i]=sumw[i-1]+1,sumv[i]=sumv[i-1]+st[i].v; else sumw[i]=sumw[i-1],sumv[i]=sumv[i-1]; ll sum=0; for(int i=1;i<=m;i++) sum+=(sumw[q[i].r]-sumw[q[i].l-1])*(sumv[q[i].r]-sumv[q[i].l-1]); //q【i】.l 值也在区间内 min1=min(min1,abs(sum-s)); if(sum>s) left=mid+1; sum>s,可知,W过小,需要变大 else right=mid-1; } cout<<min1; return 0; }

    P2678 跳石头

     洛谷
     
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define maxn 50010
    long long sum[maxn],n,cont,m;
    bool check(long long x)
    {
        long long s=0;cont=0;
        for(int i=1;i<=n+1;i++) if(sum[i]-s<x) cont++;else s=sum[i];//大佬写的一个代码
        return cont>m;
    }
    int main()
    {
        long long l,ans;
        cin>>l>>n>>m;
        for(int i=1;i<=n;i++) cin>>sum[i];
        long long left=1,right=l;
        sum[n+1]=l;
        while(left<=right){
            long long mid=(left+right)/2;
            if(check(mid)) right=mid-1;else ans=mid,left=mid+1;//mid是当前可行解,需要记录下来
        }
        cout<<ans<<endl;
        return 0;
    }

    Vijos / 题库 /

    隐形的翅膀

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    using namespace std;
    #define pre 0.6180339887498949
    #define maxn 50000
    long long length[maxn];
    long long rig,lef,mid,n,min1,min2;
    double mi,mx;
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;i++) cin>>length[i];
        sort(length+1,length+n+1);
        for(int i=1;i<=n;i++)
        {
            long long len=length[i];
            lef=1;rig=n;
            while(lef<=rig)
            {
                mid=(lef+rig)/2;
                mi=(double)length[mid]/(double)len;
                if(fabs(mx-pre)>fabs(mi-pre)) mx=mi,min1=i,min2=mid;//刚开始将这段放到二分外面,wa。应该是在循环外面少考虑些情况。
                if(mi>pre) rig=mid-1;//通过对比,刚开始受之前做的一道题误导,外加自己记串了,刚开始是通过比较与黄金分割的差距,少考虑些情况
                else lef=mid+1;
            }
        }
        cout<<min(length[min1],length[min2])<<endl;
        cout<<max(length[min1],length[min2]);
        return 0;
    }
  • 相关阅读:
    Typora 使用 Markdown 嵌入 LaTeX 数学公式符号语法
    爬虫常用的 urllib 库知识点
    执行Go程序的三种方式及Go语言关键字
    Win10 安装 MongoDB 3.6.5 失败的问题
    笨办法理解动态规划算法
    EclipseEE的Web开发环境配置(使用Tomcat作为Web服务器)
    二分类神经网络公式推导过程
    B+树在磁盘存储中的应用
    JAVA NIO工作原理及代码示例
    B树和B+树的插入、删除图文详解
  • 原文地址:https://www.cnblogs.com/Showend/p/12339719.html
Copyright © 2011-2022 走看看