二分答案例题

二分答案

一.求最小值的最大值

例题1 洛谷P2678 跳石头

在这里插入图片描述
代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll lll,n,m;
ll dis[50005];
ll f(ll down)
{
    dis[0]=0;
    dis[n+1]=lll;
    ll cnt=0;
    ll last=0;
    for(int i=1;i<=n+1;i++)
    {
        if(dis[i]-last<down)
        {
            cnt++;
        }
        else last=dis[i];
    }
    return cnt;
}
ll find2()
{
    ll l=0;
    ll r=lll;
    while(l<r)
    {
        ll mid=(r+l+1)/2;
        if(f(mid)<=m) l=mid;
        else r=mid-1;
    }
    return l;
}
int main()
{
    cin>>lll>>n>>m;
    for(int i=1;i<=n;i++) cin>>dis[i];
    cout<<find2()<<endl;
    return 0;
}

例题2 洛谷P2855 奶牛跳房子

在这里插入图片描述
代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int L,n,m;
const int N=5e4+5;
int a[N];
bool check(int x)
{
    int pos=0;
    int cnt=0;
    for(int i=1;i<=n+1;i++)
    {
        if(a[i]-a[pos]<x)  cnt++;
        else pos=i;
    }
    //if(pos!=n+1) return false;
    if(cnt>m) return false;
    else return true;
}
int find(int k)
{
    int l=1,r=L;
    while(l<r)
    {
        int mid=(l+r+1)>>1;
        //cout<<check(mid)<<endl;
        if(check(mid)) l=mid;
        else r=mid-1;
    }
    return l;
}
signed main()
{
    cin>>L>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    sort(a+1,a+n+1);
    a[n+1]=L;
    cout<<find(m)<<endl;
    return 0;
}

二.求最大值的最小值

例题1 洛谷P1182 数列分段

在这里插入图片描述
代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[100005];
int n,m;
int f(ll up)
{
    ll sum=0;
    int cnt=1;
    for(int i=1;i<=n;i++)
    {
        if(a[i]>up) return -1;
        if(sum+a[i]<=up) sum+=a[i];
        else sum=a[i],cnt++;
    }
    return cnt;
}
int find1()
{
    ll l=*max_element(a+1,a+n+1);
    ll r=0;
    for(int i=1;i<=n;i++) r+=a[i];
    while(l<r)
    {
        ll mid=(l+r)/2;
        if(f(mid)<=m) r=mid;
        else l=mid+1;
    }
    return l;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    cout<<find1()<<endl;
    return 0;
}

例题2 洛谷P1396 营救

在这里插入图片描述
代码

#include<bits/stdc++.h>
using namespace std;
const int N=2e4+5;
int head[N],e[N],w[N],ne[N],idx=0;
bool vis[N];
int n,m,s,t;
void add(int a,int b,int c)
{
    e[idx]=b;
    w[idx]=c;
    ne[idx]=head[a];
    head[a]=idx++;
}
bool flag=false;
/*
void dfs(int s,int t,int x)
{
    //cout<<1<<endl;
    vis[s]=true;
    if(flag) return ;
    if(s==t)
    {
        flag=true;
        return ;
    }
    for(int i=head[s];i!=-1;i=ne[i])
    {
        int ta=e[i];
        if(!vis[ta])
        {
            if(w[i]<=x) dfs(ta,t,x);
            if(flag) return ;
            vis[ta]=false;
        }
    }
}
*/
queue<int> q;
bool bfs(int s,int t,int x)
{
    while(q.size()) q.pop();
    memset(vis,false,sizeof(vis));
    q.push(s);
    while(q.size())
    {
        int pos=q.front();
        q.pop();
        if(pos==t) return true;
        if(vis[pos]) continue;
        vis[pos]=true;
        for(int i=head[pos];i!=-1;i=ne[i])
        {
            int ta=e[i];
            if(!vis[ta])
            {
                if(w[i]>x) continue;
                else q.push(ta);
            }
        }
    }
    return false;
}
bool f(int s,int t,int x)
{
    memset(vis,false,sizeof(vis));
    //flag=false;
    //dfs(s,t,x);
    //return flag;
    return bfs(s,t,x);
}
int find()
{
    int l=0,r=1e4+5;
    while(l<r)
    {
        int mid=(l+r)>>1;
        //cout<<f(s,t,mid)<<endl;
        if(f(s,t,mid)) r=mid;
        else l=mid+1;
    }
    return l;
}
int main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);
    cin>>n>>m>>s>>t;
    memset(head,-1,sizeof(head));
    for(int i=1;i<=m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
        add(b,a,c);
    }
    cout<<find()<<endl;
    return 0;
}

三.求满足条件的最小值

例题1 洛谷P1638 逛画展

在这里插入图片描述

转化->求满足能看到所有画师的画所需的最小值
代码

/*#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5;
const double eps=1e-8;
double l[N];
int n,k;
bool check(double x)
{
    int cnt=0;
    for(int i=1;i<=n;i++) cnt+=floor(l[i]/x);
    if(cnt>=k) return true;
    else return false;
}
double find1()
{
    double ll=0.0;
    double r=0.0;
    for(int i=1;i<=n;i++) r=max(l[i],r);
    while(r-ll>eps)
    {
        double mid=(ll+r)/2.0;
        if(check(mid)) ll=mid;
        else r=mid;
    }
    return ll;
}
char res[100];
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>l[i];
    double ans=find1();
    sprintf(res,"%.3lf",ans);
    res[strlen(res+1)]='\0';
    printf("%s",res);
    return 0;
}
*/

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m,a[N];
int resl,resr;
int vis[N];
bool check(int x)
{
    memset(vis,0,sizeof(vis));
    int cnt=0;
    for(int i=1;i<=x;i++)
    {
        if(vis[a[i]]==0) cnt++;
        vis[a[i]]++;
    }
    if(cnt>=m)
    {
        resl=1,resr=x;
        return true;
    }
    for(int i=x+1;i<=n;i++)
    {
        vis[a[i-x]]--;
        if(vis[a[i-x]]==0) cnt--;
        if(vis[a[i]]==0) cnt++;
        vis[a[i]]++;
        if(cnt>=m)
        {
            resl=i-x+1,resr=i;
            return true;
        }
    }
    return false;
}
int find1()
{
    int l=0,r=1e6+5;
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    }
    return l;
}
void solve()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    find1();
    cout<<resl<<" "<<resr<<endl;
}
int main()
{
    solve();
    return 0;
}

例题2 洛谷P4058 木材

在这里插入图片描述
代码

#include<bits/stdc++.h>
#define int ull
//#define int long long
using namespace std;
typedef unsigned long long ull;
const int N=2e5+5,inf=0x3f3f3f3f;
int n,s,ll;
int h[N],a[N];
int lh[N];
bool check(int x)
{
    int cnt=0;
    int sum=0;
    for(int i=1;i<=n;i++) lh[i]=h[i];
    int tmp=0;
    for(int j=1; j<=n; j++)
    {
        if(lh[j]+x*a[j]>=ll) tmp+=lh[j]+x*a[j];
        //lh[j]+=a[j];
        if(tmp>=s) return true;
    }
    return false;
}
int find2()
{
    int l=0,r=1e18;
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    }
    return l;
}
signed main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);
    cin>>n>>s>>ll;
    for(int i=1;i<=n;i++) cin>>h[i];
    for(int i=1;i<=n;i++) cin>>a[i];
    cout<<find2()<<endl;
    return 0;
}

四.求满足条件的最大值

例题1 洛谷P1577 切绳子

在这里插入图片描述

注意
本题最后要求的不是四舍五入,而是直接保留。最后三行很重要

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5;
const double eps=1e-8;
double l[N];
int n,k;
bool check(double x)
{
    int cnt=0;
    for(int i=1;i<=n;i++) cnt+=floor(l[i]/x);
    if(cnt>=k) return true;
    else return false;
}
double find1()
{
    double ll=0.0;
    double r=0.0;
    for(int i=1;i<=n;i++) r=max(l[i],r);
    while(r-ll>eps)
    {
        double mid=(ll+r)/2.0;
        if(check(mid)) ll=mid;
        else r=mid;
    }
    return ll;
}
char res[100];
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>l[i];
    double ans=find1();
    
    sprintf(res,"%.3lf",ans);
    res[strlen(res+1)]='\0';
    printf("%s",res);
    
    return 0;
}

例题2 洛谷P2440 木材加工

在这里插入图片描述

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int len[N];
int n,k;
bool check(int x)
{
    int res=0;
    for(int i=1;i<=n;i++) res+=len[i]/x;
    return res>=k;
}
int find2()
{
    int l=0;
    int r=1e8+1;
    //for(int i=1;i<=n;i++) r=max(r,len[i]);
    while(l<r)
    {
        int mid=(l+r+1)>>1;
        //cout<<f(mid)<<endl;
        if(check(mid)) l=mid;
        else r=mid-1;
    }
    return l;
}
signed main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>len[i];
    cout<<find2()<<endl;
    return 0;
}

例题3 洛谷P2920 Time Management S

在这里插入图片描述

代码

#include<bits/stdc++.h>
using namespace std;

const int N=1e3+5;


struct node_
{
    int t,s;
    friend bool operator < (const node_ x,const node_ y)
    {
        return x.s<y.s;
    }
}node[N];
int n,maxn;

bool check(int x)
{
    for(int i=1;i<=n;i++)
    {
        x+=node[i].t;
        if(x>node[i].s) return false;
    }
    return true;
}
int find()
{
    int l=-1e5,r=1e5;
    while(l<r)
    {
        int mid=(l+r+1)>>1;
        if(check(mid)) l=mid;
        else r=mid-1;
    }
    return l;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>node[i].t>>node[i].s;
        maxn=max(node[i].s,maxn);
    }
    sort(node+1,node+n+1);
    int res=find();
    if(res<0||res>=maxn) cout<<"-1"<<endl;
    else cout<<res<<endl;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值