FJUT 2485 数列分段II

题目地址:http://59.77.139.92/Problem.jsp?pid=2485

数列分段II

TimeLimit:1000MS  MemoryLimit:128MB
64-bit integer IO format:%lld
 
Problem Description

对于给定的一个长度为N的正整数数列A[i],现要将其分成MMN)段,并要求每段连续,且每段和的最大值最小

关于最大值最小

例如一数列4 2 4 5 1要分成3段

将其如下分段:

[4 2][4 5][1]

第一段和为6,第2段和为9,第3段和为1,和最大值为9。

将其如下分段:

[4][2 4][5 1]

第一段和为4,第2段和为6,第3段和为6,和最大值为6。

并且无论如何分段,最大值不会小于6。

所以可以得到要将数列4 2 4 5 1要分成3段,每段和的最大值最小为6。

Input

输入的第1行包含两个正整数N,M,第2行包含N个空格隔开的非负整数A[i],含义如题目所述。

(N≤100000,M≤N, A[i]之和不超过109。)

Output

输出仅包含一个正整数,即每段和最大值最小为多少。

SampleInput
5 3
4 2 4 5 1
SampleOutput
6

分析:由题 需要推出最小值可能在的范围。
然后将这个范围进行二分,看其中的值能不能实现。
对于每个值,我们需要推出实现当前的值最少需要的段数,
如果段数大于m则不成立。
代码如下:
#include <bits/stdc++.h> 
using namespace std;
typedef long long ll;
int c[100100];
int n,m;
int check(int mid)
{
  int sum=0;
  int num=1;
  for(int i=0;i<n;i++)
  {
      if(sum+c[i]<=mid)sum+=c[i];
      else num++,sum=c[i];
  }
//  cout<<"num"<<num<<endl;
  if(num>m)return 0;
  else return 1;
  
}
int main()
{
    int l,r,mid,ans;
    while(cin>>n>>m)
    {
        l=0;
        r=0;
        for(int i=0;i<n;i++)
        cin>>c[i],l=max(c[i],l),r+=c[i];
        while(l<r)
        {
        //    cout<<"l="<<l<<endl;
        //    cout<<"r="<<r<<endl;
            mid=(l+r)/2;
            if(check(mid))r=mid;
            else l=mid+1;
        }
        cout<<r<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/a249189046/p/6657052.html