2.划分数列(seq.pas/c/cpp)
【题目描述】
给你一个有n个元素的数列,要求把它划分成k段,使每段元素和的最大值最小
【输入格式】
第一行两个正整数n,k
第二行为此数列ai
【输出格式】
一行一个数,为题目所求答案
【样例输入】
5 2
2 1 3 4 5
【样例输出】
9
【数据规模】
30%数据 n <= 30, k <= 10
100%数据 n <= 100000, k <= n, ai <= 10^9
【时限】
1s
前面已经说了,如果只用动规,是O(n3)的时间复杂度,只能拿50分
而看到这种求最大值最小,或者最小值最大的题(类似关押罪犯)就应该想到去二分答案,就能拿100分
C++ Code
#include<cstdio>
#include<string>
using namespace std;
#define MAXN 100000+10
int n,m,a[MAXN],sum;
bool ok(int mm)
{
int num=0,s=0,i=0;
while(true)
{
s=0;
while(true)
{
if(i>=n){num++;break;}
if(s+a[i+1]<=mm)
{
s+=a[i+1];
i++;
}
else if(s+a[i+1]>mm){num++;break;}
}
//printf("s=%d i=%d num=%d\n",s,i,num);
if(i>=n)break;
}
if(num<=m)return true;else return false;
}
int main()
{
freopen("seq.in","r",stdin);
freopen("seq.out","w",stdout);
scanf("%d%d",&n,&m);
int i;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
int l=1,r=sum,mid;
while(l<r)
{
mid=l+(r-l)/2;
//printf("l=%d r=%d mid=%d\n",l,r,mid);
if(ok(mid))r=mid;else l=mid+1;
}
printf("%d",r);
}