给出一个长度为N的正整数数组,不改变数组元素的顺序,将这N个数分为K组。各组中元素的和分别为S1,S2....Sk。如何分组,使得S1至Sk中的最大值最小?
例如:1 2 3 4 5 6分为3组,{1 2 3} {4 5} {6},元素和为6, 9, 6,最大值为9。也可以分为{1 2 3 4} {5} {6}。元素和为:10 5 6,最大值为10。因此第一种方案更优。并且第一种方案的最大值是所有方案中最小的。输出这个最小的最大值。
Input
第1行:2个数N, K,中间用空格分隔,N为数组的长度,K为要分为多少组。(2 <= K < N <= 50000) 第2 - N + 1行:数组元素(1 <= A[i] <= 10^9)
Output
输出这个最小的最大值。
Input示例
6 3 1 2 3 4 5 6
Output示例
9
双二分!!!
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=5e4+10;
LL pre[maxn];
int a[maxn];
int n,k;
bool judge(LL mid)
{
LL num;
int i,j,p;
num=mid;
for(i=1;i<=k;i++) {
p=upper_bound(pre+1,pre+1+n,num)-pre;
num=mid+pre[p-1];
if(p==n+1) break;
}
if(i<=k) return false;
else return true;
}
int main()
{
LL l,r,mid;
int i,j;
scanf("%d%d",&n,&k);
for(i=1;i<=n;i++) {
scanf("%d",&a[i]);
pre[i]=(LL) pre[i-1]+a[i];
}
sort(a+1,a+1+n);
l=0;r=0;
for(i=n;i>n-(n/k+1);i--) r+=a[i];
for(i=1;i<=n/k;i++) l+=a[i];
while(l<=r) {
mid=(l+r)>>1;
if(judge(mid)) l=mid+1;
else r=mid-1;
}
printf("%I64d\n",l);
return 0;
}