P1182 数列分段 Section II
题目描述
对于给定的一个长度为N的正整数数列 A_{1\sim N}A1∼N,现要将其分成 MM(M\leq NM≤N)段,并要求每段连续,且每段和的最大值最小。
关于最大值最小:
例如一数列 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 10N≤10。
对于 40\%40% 的数据,N\leq 1000N≤1000。
对于 100\%100% 的数据,1\leq N\leq 10^51≤N≤105,M\leq NM≤N,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 }

浙公网安备 33010602011771号