首页 > 代码库 > 洛谷P1182 数列分段Section II 二分答案

洛谷P1182 数列分段Section II 二分答案

洛谷P1182 数列分段Section II

二分答案
题意:将 n 个 数 分为 m段 求一种方案,使这m段中最大的和 最小
额。。可能有点拗口,其实就是说每一种方案,都有对应的 每段和的最大值,
要求一种方案,使最大值最小

题解 :二分答案 mid为分成的最大值,
然后O(n) 判断 答案 是否可行
贪心的做下去,如果再加上就要超过了,那就新开一段

最后判断开的段数是否小于 m

1、注意要判断 如果当前这个值大于 mid,一个值就已经大于 mid了,那就直接退出
了,否则 ,这个值也只会单独算为一段的,其实他一段都放不下

2、或者还有之中方法 答案从 最大的 a[ i ] 开始枚举。。。

 

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <string>
 6 #include <algorithm>
 7 #include <iomanip>
 8 #include <iostream>
 9 using namespace std ; 
10 
11 const int maxn = 100011 ; 
12 int n,m,l,r,mid ; 
13 int a[maxn] ; 
14 
15 inline bool check( int mid ) 
16 {
17     int ans = 0,sum = 0 ; 
18     for(int i=1;i<=n;i++) 
19     {
20         if(a[ i ]>mid) return 0 ;  
21 // 1、注意要判断  如果当前这个值大于 mid,一个值就已经大于  mid了,
22 //那就直接退出了,否则 ,这个值也只会单独算为一段的,其实他一段都放不下 
23         if( sum+a[ i ] > mid ) 
24             ans++,sum = 0 ;  
25         sum+=a[ i ] ; 
26     }
27     ans++ ; 
28     return ans <= m ;  
29 }
30 
31 int main() 
32 {
33     scanf("%d%d",&n,&m) ; 
34     for(int i=1;i<=n;i++) scanf("%d",&a[ i ]) ; 
35     l = 0,r = 1e9 ; 
36     while( l<r ) 
37     {
38         mid = ( l+r )>>1 ;
39         if(check(mid)) 
40             r = mid ; 
41         else  
42             l = mid + 1 ;
43     }
44     printf("%d\n",r) ; 
45     return 0 ; 
46 }

 

洛谷P1182 数列分段Section II 二分答案