一道很好的二分题
Posted emcikem
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一道很好的二分题相关的知识,希望对你有一定的参考价值。
最大化最小值,二分找出一个数,是的所有的数都满足大于这个数,那这个数就是最小值,然后二分找到这个数字的最大值即可
二分可以最大化最小值,最小化最大值
传送门
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#define ll long long
const int maxn = 5e4+500;
const int inf = 0x3f3f3f3f;
const double eps = 1e-5;
using namespace std;
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return f*x;
}
ll a[maxn];
int n,d;
int day[maxn];
bool check(ll x){//每天都需要达到这么多的开心值
ll sum=0;//每天的开心值
int k=0;
for(int i=1;i<=d;i++){
while(sum<x){
k++;
sum+=a[k];
if(k>n)return 0;//巧克力不够吃了
}
sum/=2;
}
return 1;
}
void getans(ll x){//每天吃的值
ll sum=0;
int k=0;
for(int i=1;i<=d;i++){
while(sum<x){
k++;
sum+=a[k];
day[k]=i;
}
sum/=2;
}
}
int main(){
cin>>n>>d;
ll l=0,r=0;
for(int i=1;i<=n;i++)a[i]=read(),r+=a[i];
ll mid=0;
ll ans=0;
while(l<=r){
mid=(l+r)/2;
if(check(mid)){//找到一个最小值,每天都吃后的值都≥这个值
l=mid+1;
ans=mid;
}else r=mid-1;
}
printf("%lld\n",ans);
getans(ans);
for(ll i=1;i<=n;i++){
if(day[i])printf("%d\n",day[i]);
else printf("%d\n",d);
}
return 0;
}
以上是关于一道很好的二分题的主要内容,如果未能解决你的问题,请参考以下文章