A0544 数列分段2

数列分段2

题目描述

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

关于最大值最小:

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

将其如下分段:

[42],[45],[1]

第一段和为 6,第二段和为 9,第三段和为 1,和最大值为 9。

将其如下分段:

[4],[24],[51]

第一段和为 44,第二段和为 6,第三段和为 6,和最大值为 6。

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

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

输入格式

第一行包含两个正整数 N,M。

第二行包含 N 个空格隔开的正整数 a[i]​,含义如题目所述。

输出格式

一个正整数,即每段和最大值最小为多少。

样例 #1

样例输入 #1

5 3
4 2 4 5 1

样例输出 #1

6

提示

对于 20% 的数据:1≤N≤10

对于 40% 的数据:1≤N≤1000

对于 100% 的数据,有 1≤M≤N≤100000,且 a[i]​ 之和不超过 1000000000。 

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,a[N];
int chk(int sum)
{
	int cnt=0,rest=0;
	for(int i=1;i<=n;i++)
	{
		if(rest>=a[i])
		{
			rest-=a[i];
		}
		else
		{
			cnt++;
			rest=sum-a[i];
		}
	}
	return cnt<=m;
}
int find(int l,int r)
{
	while(l<r)
	{
		int mid=(l+r)/2;
		if(chk(mid))
		{
			r=mid;
		}
		else
		{
			l=mid+1;
		}
	}
	return l;
}
int main()
{
	cin>>n>>m;
	int l=0,r=0;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		l=max(l,a[i]);
		r+=a[i];
	}
	cout<<find(l,r);
    return 0;
}
/*~~~~~~~~~~~~~~DLZS135~~~~~~~~~~~~~~~~~~~~*/

  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值