题目:https://vjudge.net/problem/UVA-714
用二分的思想,去求满足划分区间的最小值,类似于lower_bound的实现,输出时候,从后往前推,使得后面的先满足
条件,这样可以使前面划分的区域装的数尽可能小。
#include<bits/stdc++.h>
long long a[510],sum[510];
bool is[510];
int m,k;
int judge(long long mid){
int count=0;
int pre=0;
for(int i=1;i<=m;){
while(i<=m && (sum[i]-sum[pre])<=mid) i++;
count++;
pre=i-1;
}
if(count<=k)
return true;
else
return false;
}
int main(){
int n;
scanf("%d",&n);
while(n--){
long long mid;
long long total=0;
long long low=0,high=0;
memset(is,0,sizeof(is));
scanf("%d %d",&m,&k);
for(int i=1;i<=m;i++){
scanf("%d",&a[i]);
if(low<a[i])
low=a[i];
sum[i]=sum[i-1]+a[i];
is[i]=false;
}
high=sum[m];
while(low<high){ //与lower_bound实现类似 求满足可以划分k阶段的最小的和
mid=(low+high)/2;
if(judge(mid)) high=mid;
else
low=mid+1;
}
k--;
for(int i=m;i>0;i--){
if(a[i]+total>low){
is[i]=true;
total=a[i];
k--;
}
else total+=a[i];
if(i==k){
for(;i>0;i--)
is[i]=true;
break;
}
}
for(int i=1;i<=m;i++){
printf("%d",a[i]);
if(i==m) printf("\n");
else printf(" ");
if(is[i])
printf("/ ");
}
}
}