题目大意:
给出一个数字串,将它分成 m m 个部分,要求每个部分的和的最大值最小。
思路:
很明显的二分答案。首先利用前缀和求出前个数字之和,然后 l=1,r=s[n] l = 1 , r = s [ n ] 来二分和的最大值。要注意当任意一个 s[i]−s[i−1]>m s [ i ] − s [ i − 1 ] > m 那么就必然不成立。
代码:
#include <cstdio>
#include <iostream>
using namespace std;
int n,m,s[100011],l,r,mid,sum,k;
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%d",&s[i]);
s[i]+=s[i-1]; //前缀和
}
l=1;
r=s[n];
while (l<r)
{
mid=(l+r)/2;
sum=0;
k=0;
for (int i=1;i<=n;i++)
{
if (s[i]-s[i-1]>mid) //任意一个数字超过了答案
{
sum=m+1;
break;
}
if (s[i]-s[k]>mid) //这一部分超过答案
{
sum++;
k=i-1;
if (sum>m) break;
}
}
if (sum<m) r=mid;
else l=mid+1;
}
printf("%d\n",r);
return 0;
}