数列分段II(二分)

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

关于最大值最小:

例如一数列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],含义如题目所述。

M<=N<=100000, A[i]之和不超过109

 

 

输出

 

 

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

 

 

样例输入

 

样例输出

 

解题思路:最大值的最小 二分 

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int sum;
 6 int maxx;
 7 int n,m;
 8 int arr[100005];
 9 
10 int check(int num){
11     int ans=0,res=0;
12     for(int i=1;i<=n;i++){
13         if(ans+arr[i]<=num) ans+=arr[i];
14         else ans=arr[i],res++;
15     }
16     if(res>=m) return 0;
17     else return 1;
18 }
19 
20 int Calculation(int left,int right){
21     while(left<=right){
22         int mid=left+right>>1;
23         if(check(mid)==1) right=mid-1;
24         else left=mid+1;
25     }
26     return left;
27 }
28 
29 int main(){
30     ios::sync_with_stdio(false);
31     cin>>n>>m;
32     for(int i=1;i<=n;i++){
33         cin>>arr[i];
34         sum+=arr[i];
35         maxx=max(maxx,arr[i]);
36     }
37     cout << Calculation(maxx,sum) << endl;
38     return 0;
39 }
View Code

 

posted @ 2019-07-27 16:48  厂长在线养猪  Views(394)  Comments(0Edit  收藏  举报