Fork me on GitHub

【luoguP1182】数列分段 Section II

 

题目描述

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

关于最大值最小:

例如一数列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。

输入格式

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

2行包含N个空格隔开的非负整数A_i,含义如题目所述。

输出格式

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

输入输出样例

输入 #1
5 3
4 2 4 5 1
输出 #1
6

说明/提示

对于20%的数据,有N≤10

对于40%的数据,有N≤1000

对于100%的数据,有N≤100000,M≤N, A_iN100000之和不超过10^9

思路:

  看见这道题,让求每段的最大值最小,显然二分答案,我们二分一个val,左端点为序列的最大值,右端点为序列的和,

  每次二分,如果二分的只满足在限定次数内分成,则r=min-1,否则r=mid+1;

  注意scanf中的括号内不能有空格,否则不输出,还有,

  在使用快读是,读的数与数之间要用分号,不能用逗号,因为C++ 先执行逗号后面的内容,容易出锅。

代码:

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int l,r,n,m,a[100100],yilin,sum,mid;
bool judge(int x)
{
	yilin=0,sum=0;
	for (int i=1;i<=n;i++)
	{
		if(sum+a[i]<=x) sum+=a[i];
		else sum=a[i] , yilin++;
	}
	return (yilin >= m);
}
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		r+=a[i];
		l=max(l , a[i] );
	}
	while(l<=r)
	{
		 mid=(l+r) / 2;
		if(judge(mid))l = mid + 1;
		else r = mid-1;
	}
	printf("%d\n",l);
	return 0;
}

  

 

 

 

posted @ 2019-09-17 18:10  yelir  阅读(272)  评论(0编辑  收藏  举报