二分查找算法

整数二分

在这里插入图片描述

在这里插入图片描述

浮点数二分

注意: < < 1 \color{blue}{注意: <<1 } 注意:<<1只适用于整数

一般为最大化查找

在这里插入图片描述
一元三次方程求解(1024)
在这里插入图片描述

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define fi first
    #define se second
    #define pb push_back
    #define eb emplace_back
    #define rep(i,x,y) for(int i = (x); i <= (y); i++)
    #define per(i,x,y) for(int i = (x); i >= (y); i--)
    #define all(x) (x).begin(),(x).end()
    #define SZ(x) ((int)(x).size())
    #define endl '\n'
    #define ms(x, n) memset(x,n,sizeof (x));
    using ll = long long;
    const int N = 1e6 + 10, mod = 998244353;

    double a,b,c,d;

    double fun(double x){
        return a*x*x*x+b*x*x+c*x+d;
    }

    double mfind(double l,double r){
    	//区分:浮点数是>
        while(r-l>1e-4){
            double mid=(l+r)/2;
            // 函数零点定理
            if(fun(mid)*fun(r)<0) l=mid;//最大化
            else r=mid; 
        }
        return l;

    }

    int main(){
        cin>>a>>b>>c>>d;

        rep(i,-100,100){
            double y1=fun(i),y2=fun(i+1);
            if(!y1) printf("%.2lf ",1.0*i);//y1==0,即表示根
            //1.0*i:将i转化为double类型
            if(fun(i)*fun(i+1)<0) printf("%.2lf ",mfind(i,i+1));
        }

        return 0;
    }

二分答案

1.百搭算法:贪心,DP,搜索,前缀和等
2. 画出函数图像,找出哪里是可行区,返回真

在这里插入图片描述

木材加工(2240)

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define rep(i,x,y) for(int i = (x); i <= (y); i++)
#define per(i,x,y) for(int i = (x); i >= (y); i--)
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define endl '\n'
#define ms(x, n) memset(x,n,sizeof (x));
using ll = long long;
const int N = 1e6 + 10, mod = 998244353;

int n,k,a[N];

bool check(int x){
    ll y=0;
    rep(i,1,n) y+=a[i]/x;
    return y>=k;
}

int find(){
    int l=0,r=1e8+10;
    while(l+1<r){
        int mid=l+r>>1;
        if(check(mid)) l=mid;
        else r=mid;
    }
    return l;
}

int main(){    
    cin>>n>>k;
    rep(i,1,n) cin>>a[i];
    
    cout<<find();

    return 0;
}

跳石头(2678)

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define rep(i,x,y) for(int i = (x); i <= (y); i++)
#define per(i,x,y) for(int i = (x); i >= (y); i--)
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define endl '\n'
#define ms(x, n) memset(x,n,sizeof (x));
using ll = long long;
const int N = 1e6 + 10, mod = 998244353;

int n,m,L;
int a[N];

bool check(int x){
    int last=0,cnt=0;
    rep(i,1,n+1){
        if(a[i]-a[last]<x) cnt++;
        else last=i;
    }
    return cnt<=m;
}

int find(){
    int l=0,r=1e8+10;
    while(l+1<r){
        int mid=l+r>>1;
        if(check(mid)) l=mid;
        else r=mid;
    }
    return l;
}

int main(){
    cin>>L>>n>>m;

    rep(i,1,n) cin>>a[i];

    a[n+1]=L;

    cout<<find();


    return 0;
}

聪明的质检员(1314)

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define rep(i,x,y) for(int i = (x); i <= (y); i++)
#define per(i,x,y) for(int i = (x); i >= (y); i--)
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define endl '\n'
#define ms(x, n) memset(x,n,sizeof (x));
using ll = long long;
const int N = 1e6 + 10, mod = 998244353;

int n,m,w[N],v[N],l[N],r[N];//重量w,价值v
ll s,sn[N],sv[N],ans=1e18;

bool check(int W){
    ms(sn,0);
    ms(sv,0);
    rep(i,1,n){
        if(w[i]>=W) sn[i]=sn[i-1]+1,sv[i]=sv[i-1]+v[i];
        else sn[i]=sn[i-1],sv[i]=sv[i-1];
    }
    ll y=0;
    rep(i,1,m)
        y+=(sn[r[i]]-sn[l[i]-1])*(sv[r[i]]-sv[l[i]-1]);
    ans=min(ans,llabs(y-s));//取最优解
    return s>=y;
}

ll find(){
    int l=0,r=1e6+10;
    while(l+1<r){
        int mid=l+r>>1;
        if(check(mid)) r=mid;
        else l=mid;
    }
    return ans;
}

int main(){
    cin>>n>>m>>s;
    rep(i,1,n) cin>>w[i]>>v[i];
    rep(i,1,m) cin>>l[i]>>r[i];
    cout<<find();

    return 0;
}

借教室(1083)

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define rep(i,x,y) for(int i = x; i <= y; i++)
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define endl '\n'
#define ms(x, n) memset(x,n,sizeof (x));
using ll = long long;
const int N = 1e6 + 10, mod = 998244353;

int n,m,r[N],d[N],s[N],t[N];
ll num[N];//教室需求数

bool check(int x){
    ms(num,0);
    rep(i,1,x){//ding dan
        num[s[i]]+=d[i];
        num[t[i]+1]-=d[i];
    }
    rep(i,1,n){//day
        num[i]+=num[i-1];
        if(r[i]<num[i]) return 0;
    }
    return 1;

}

int find(){//ding dan
    int l=0,r=m+1;
    while(l+1<r){
        int mid=l+r>>1;
        if(check(mid)) l=mid;
        else r=mid;
    }
    return l;
}

int main(){ 
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    cin>>n>>m;

    rep(i,1,n) cin>>r[i];

    rep(i,1,m) cin>>d[i]>>s[i]>>t[i];

    if(check(m)){
        puts("0");
        return 0;
    }
    cout<<"-1"<<endl<<find()+1;

    return 0;
}

刺杀大使(1902 )

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define rep(i,x,y) for(int i = x; i <= y; i++)
#define per(i,x,y) for(int i = x; i >= y; i--)
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define endl '\n'
#define ms(x, n) memset(x,n,sizeof (x));
using ll = long long;
const int N = 1e3 + 10, mod = 998244353;

int dx[4]={-1,0,1,0},dy[4]={0,-1,0,1};
int n,m,vis[N][N],p[N][N];

bool dfs(int x,int y,int P){
    if(x==n) return 1;

    vis[x][y]=1;

    rep(i,0,3){//attendent!!
        int a=x+dx[i],b=y+dy[i];
        if(a>=1 && a<=n && b>=1 && b<=m && !vis[a][b] && p[a][b]<=P)
            if(dfs(a,b,P)) 
                return 1;
    }
    return 0;
}

int find(){
    int l=-1,r=1e3+10;
    while(l+1<r){
        int mid=l+r>>1;
        ms(vis,0);
        if(dfs(1,1,mid)) r=mid;//都是从(1,1)出发
        else l=mid;
    }
    return r;
}

int main(){
    cin>>n>>m;

    rep(i,1,n)
        rep(j,1,m)
            cin>>p[i][j];

    cout<<find();


    return 0;
}

银行贷款(1163 )

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define rep(i,x,y) for(int i = x; i <= y; i++)
#define per(i,x,y) for(int i = x; i >= y; i--)
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define endl '\n'
#define ms(x, n) memset(x,n,sizeof (x));
using ll = long long;
const int N = 1e6 + 10, mod = 998244353;

int a,b,c;

bool check(double x){
    double s=a;
    rep(i,1,c){
        s=(1+x)*s-b;
    }
    return s>=0;
}

double find(){
    double l=0,r=10;
    while(r-l>=1e-5){
        double mid=(l+r)/2;
        if(check(mid)) r=mid;
        else l=mid;
    }
    return r;
}

int main(){
    cin>>a>>b>>c;

    printf("%.1lf",find()*100);

    return 0;
}
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值