P1182 数列分段 Section II

题目描述

对于给定的一个长度为N的正整数数列 A_{1\sim N}A1N,现要将其分成 MM(M\leq NMN)段,并要求每段连续,且每段和的最大值最小。

关于最大值最小:

例如一数列 4\ 2\ 4\ 5\ 14 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]

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

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

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

输入格式

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

第 22 行包含 NN 个空格隔开的非负整数 A_iAi,含义如题目所述。

输出格式

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

输入输出样例

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

说明/提示

对于 20\%20% 的数据,N\leq 10N10。

对于 40\%40% 的数据,N\leq 1000N1000。

对于 100\%100% 的数据,1\leq N\leq 10^51N105,M\leq NMN,A_i < 10^8Ai<108, 答案不超过 10^9109。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m;
 4 int r,l,mid;
 5 
 6 inline bool judge(int x,int a[])
 7 {
 8     int sum=0,tim=0;//sum记录数的和,tim记录数的个数
 9     for(int i=0;i<n;i++)
10       {
11         if(sum+a[i]<=x)
12             sum+=a[i];//贪心判断是否为满足x
13         else
14             sum=a[i],tim++;//上面条件不成立,就累计数字个数
15       }
16       return tim>=m;//比较已经使用的数字个数是否超过题目中要求个数
17 }
18 int main()
19 {
20     cin>>n>>m;
21     int a[n];
22     for(int i=0;i<n;i++)
23     {
24         cin>>a[i];
25         r+=a[i];//这个点肯定比所有元素的和的值小
26         l=max(l,a[i]);//这个点一定比单个数大于等于
27         //所以二分答案,因为得到了答案范围
28     }
29     while(l<r)
30     {
31         mid=l+((r-l)>>1);
32         //sum=0,tim=0;
33         if(judge(mid,a))
34             l=mid+1;
35         else
36             r=mid;
37     }
38     cout<<l;
39     return 0;
40 }

 

 

posted @ 2020-10-28 20:12  BlackSnow  阅读(193)  评论(0)    收藏  举报