洛谷1182 数列分段`Section II` 二分答案

题目

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

关于最大值最小:

例如一数列 4 2 4 5 142451 要分成 33 段

将其如下分段:

[4 2][4 5][1][42][45][1]

第一段和为 66 ,第 22 段和为 99 ,第 33 段和为 11 ,和最大值为 99 。

将其如下分段:

[4][2 4][5 1][4][24][51]

第一段和为 44 ,第 22 段和为 66 ,第 33 段和为 66 ,和最大值为 66 。

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

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

题解

最大值最小,二分答案,然后模拟判定答案可行性即可

代码

#include <cstdio>

using namespace std;

int n,m,sum,ans,l,r;
int a[100005];

bool work(int max){
    int k=n,c=max,h=m-1;
    while (k){
        if (a[k]>max) return false;
        if (c-a[k]>=0) c-=a[k];
               else c=max-a[k],h--;
        k--;
    }
    if ((!k)&&(h>=0)) return true;
               else return false; 
}

int main(){
//  freopen("r","testdata.in",stdin);
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        sum+=a[i];
    }
    l=1,r=sum;
    while (l<=r){
        int mid=(l+r)/2;
        if (work(mid)) ans=mid,r=mid-1;
                  else l=mid+1;
    } 
    printf("%d",ans); 
}

猜你喜欢

转载自blog.csdn.net/yjy_aii/article/details/81667118