這是我找到的一篇很久之前為了讓我更好理解二分寫的詳細題解
題目連結
code:
#include <bits/stdc++.h>
#define int long long
#define MAXN 0x3f3f3f3f3f3f3f3f
#define MINN -0x3f3f3f3f3f3f3f3f
#define Mirai ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;
const int N=1e5+29;
int n,k,maxn;
int a[N];
bool check(int x){//x表示小段木頭的長度
int ans=0;
for(int i=1;i<=n;i++) ans+=a[i]/x;//列舉每根原木,將能從這根原木中切割出長度為x的小段木頭的數量累加到ans中
return ans>=k;//這裡取了等號給l
}
int binary(){
int l=0,r=maxn+1;//這裡l最好從0開始,r從maxn+1開始,避免出鍋
while(l+1<r){//老師講的最原始的方法【也是我覺得最好理解的
int mid=l+r>>1;
if(check(mid)) l=mid;
else r=mid;
}
return l;//因為等號給了l,所以答案儲存在l裡
}
signed main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
maxn=max(maxn,a[i]);//用於確定二分中r的初始值
}
cout<<binary();
return 0;
}
注意事項:
注意二分中=
給的物件,若 \(l\) 取到=
,答案儲存在 \(l\) 中,反之則在 \(r\) 中。
二分中建議初始化 \(l=0,r=maxn+1\) 避免出現一些難調的bug
如果擔心不能切割的情況,即答案為 \(0\) 時會出錯,可在main
函式中特判:
int sum=0;
for(int i=1;i<=n;i++){
cin>>a[i];
sum+=a[i];
}
if(sum<k){
cout<<0;
return 0;
}