P1182 数列分段 Section II

本文介绍了如何解决将正整数数列分成M段,使得每段连续且每段和最大值最小的问题。通过二分搜索策略,确定合适的段和边界,以确保段数不超过M且和最小。给出的具体例子展示了如何将数列[4, 2, 4, 5, 1]分成3段,使得最大和最小为6。" 121104902,9140234,Spring Data JPA实战:从入门到测试,"['Java', 'Spring Framework', '数据库', 'ORM', 'Spring Data']
摘要由CSDN通过智能技术生成

题目大意:

题目描述
对于给定的一个长度为N的正整数数列 A_{1\sim N}A 1∼N,现要将其分成 M(M\leq NM≤N)段,并要求每段连续,且每段和的最大值最小。
关于最大值最小:
例如一数列 4\ 2\ 4\ 5\ 1 要分成 33 段。
将其如下分段:
[4\ 2][4\ 5][1]
[4 2][4 5][1]
第一段和为 66,第 22 段和为 99,第 33 段和为 11,和最大值为 99。
将其如下分段:
[4][2\ 4][5\ 1]
[4][2 4][5 1]
第一段和为 4,第 2 段和为 6,第 3 段和为 6,和最大值为 6。
并且无论如何分段,最大值不会小于 66。
所以可以得到要将数列 4\ 2\ 4\ 5\ 1要分成 3 段,每段和的最大值最小为 6。
输入格式
第 1 行包含两个正整数 N,M。
第 2行包含 N 个空格隔开的非负整数 A_iA
i​,含义如题目所述。
输出格式
一个正整数,即每段和最大值最小为多少。
样例
输入 #1
5 3
4 2 4 5 1
输出 #1
6
说明/提示
对于 20%20% 的数据,N\leq 10N≤10。
对于 40%40% 的数据,N\leq 1000N≤1000。
对于 100%100% 的数据,1\leq N\leq 10^51≤N≤10 5,M\leq NM≤N,A_i < 10^8A i<108,答案不超过 10^910 9 。

解题思路:

左端点设为数列中最大的数,右端点设为数列的和,对其进行二分

以每次二分出的数mid作为每段和来判断数列可以分为多少段,假设为K段

若K>m,说明分的段数过多,应将mid变大,则使左端点=mid+1

若K<=m,尝试更小的mid, 令右端点=mid-1

代码:

#include <bits/stdc++.h>
using namespace std;
int n,m,x,f[100001],p,l,r,mid,sum,ans,maxn;
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
    	cin>>x;
    	f[i]=f[i-1]+x,maxn=max(maxn,x);
    }
    l=maxn; 
    r=f[n];
    while(l<=r){
        mid=(l+r)>>1;
        p=1,sum=1;
        for(int i=2;i<=n;i++){
            if(f[i]-f[p-1]>mid)
            p=i,sum++;
        }
        if(sum>m){
        	l=mid+1;
        }else{
        	r=mid-1;
        	ans=mid;
        }
    }
    cout<<ans;
    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值