题目描述
依次给出n个正整数A1,A2,… ,An,将这n个数分割成m段,每一段内的所有数的和记为这一段的权重, m段权重的最大值记为本次分割的权重。问所有分割方案中分割权重的最小值是多少?
输入描述:
第一行依次给出正整数n,m,单空格切分;(n <= 10000, m <= 10000, m <= n) 第二行依次给出n个正整数单空格切分A1,A2,… ,An (Ai <= 10000)
输出描述:
分割权重的最小值
示例1
输入
复制
5 3 1 4 2 3 5
输出
复制
5
说明
分割成 1 4 | 2 3 | 5 的时候,3段的权重都是5,得到分割权重的最小值。
题解:如果m=1的话,即将n个数分成1段,分割权重的最小值即为n个数的和记为l。如果m=n的话,即将n个数分为n段,分割权重的最小值即为n个数中的最大值记为r。如果m > 1 && m < n 的话答案一定在l和r之间, 我们二分枚举l和r之间的值即可。
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
int n, m;
int l = 0, r = 0;
int ret = INT_MAX;
cin >> n >> m;
vector <int> a(n);
for (int i = 0; i < n; i++){
scanf("%lld", &a[i]);
l = max(a[i], l);
r += a[i];
}
auto check = [&](int value) -> int{
int ans = 0, seg = 0;
for (int i = 0; i < n; i++){
if(ans + a[i] > value){
ans = a[i];
seg++;
if(seg >= m){
return 0;
}
} else {
ans += a[i];
}
}
return 1;
};
while(l <= r){
int mid = (l + r) >> 1;
if(check(mid)){
ret = min(ret, mid);
r = mid - 1;
} else {
l = mid + 1;
}
}
cout << ret << "\n";
return 0;
}