Bootstrap

洛谷 P2440 木材加工

思路:二分答案

有 n 根木头,现在想把这些木头切割成 k 段长度为 l 的小段木头(木头有可能有剩余)。

希望得到的小段木头越长越好,请求出 l 的最大值,

对于切出来的小段木头,长度最短是1,最长是最长的原木的长度,在这个区间进行二分答案,因为答案就在这个区间里面,对于每棵原木,用cnt加上它能切出来多少段小木头,与k进行比较,如果比k大,说明l太短了,l=mid,找右边区域;反之,如果比k小,说明l太长了,r=mid-1,找左边区域;

如果这些原木的总长度都比k小,那说明切不出来,就输出0即可;

#include<bits/stdc++.h>
#define endl "\n";
using namespace std;
typedef long long ll;
const int N=1e6+5;
typedef pair<int,int> PII;
const int INF=0x3f3f3f3f;
typedef struct node{

}node;
void IOS(){
	 ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
}
//试试upper_bound(),lower_bound(); 
ll n,k;
void solve(){
	cin>>n>>k;
	vector<int>vec(n);
	ll all=0;
	for(int i=0;i<n;++i){
		cin>>vec[i];
		all+=vec[i];
	}
	if(all<k){
		cout<<0;
	}
	else{
		sort(vec.begin(),vec.end());
		int l=1,r=vec.back();
		while(l<r){
			int mid=l+r+1>>1;
			int cnt=0;
			for(int i=0;i<n;++i){
				cnt+=vec[i]/mid;
			}
			if(cnt>=k){
				l=mid;
			}
			else{
				r=mid-1;
			}
		}
		cout<<l;
	}
}
int main(){
	IOS();
	solve();
	return 0;
}

;