数列分段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 }