数列分段 Section II

数 列 分 段   S e c t i o n   I I 数列分段\ Section\ II  Section II

题目链接:luogu P1182

题目

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

关于最大值最小:
例如一数列 4 4 4 2 2 2 4 4 4 5 5 5 1 1 1要分成 3 3 3

将其如下分段:
[ 4 [4 [4 2 ] [ 4 2][4 2][4 5 ] [ 1 ] 5][1] 5][1]
第一段和为 6 6 6,第 2 2 2段和为 9 9 9,第 3 3 3段和为 1 1 1,和最大值为 9 9 9

将其如下分段:
[ 4 ] [ 2 [4][2 [4][2 4 ] [ 5 4][5 4][5 1 ] 1] 1]
第一段和为 4 4 4,第 2 2 2段和为 6 6 6,第 3 3 3段和为 6 6 6,和最大值为 6 6 6

并且无论如何分段,最大值不会小于 6 6 6
所以可以得到要将数列 4 4 4 2 2 2 4 4 4 5 5 5 1 1 1要分成 3 3 3段,每段和的最大值最小为 6 6 6

输入

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

输出

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

样例输入

5 3
4 2 4 5 1

样例输出

6

数据范围

对于 20 % 20\% 20%的数据,有 N ≤ 10 N≤10 N10
对于 40 % 40\% 40%的数据,有 N ≤ 1000 N≤1000 N1000
对于 100 % 100\% 100%的数据,有 N ≤ 100000 , M ≤ N , A i N≤100000,M≤N, A_i N100000,MN,Ai之和不超过 1 0 9 10^9 109

思路

这道题就是一道二分。
就二分答案,看看最少要分成多少段。超过 m m m段就不可以,答案在右边;否则就可以,答案在左边。
最后输出 l l l即可

代码

#include<cstdio>
#define max(x,y) (x)>(y)?(x):(y)
using namespace std;
int n,m,a[100001],l,r,temp,ans;
int main()
{
	scanf("%d%d",&n,&m);//读入
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);//读入
		l=max(l,a[i]);//找到最小答案
		r+=a[i];//找到最大的答案
	}
	while (l<r)//二分
	{
		int mid=(l+r)/2;
		ans=1;temp=0;//初始化
		for (int i=1;i<=n;i++)//统计最少要分成多少段
		 if (a[i]+temp>mid)
		 {
		 	ans++;
		 	if (ans>m) break;
			temp=a[i];
		 }
		  else temp+=a[i];
		if (ans>m) l=mid+1;//超过了m段(不行)
		 else r=mid;//没有超过(可以)
	}
	printf("%d",l);//输出
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值