模板P1182数列分段II——二分答案

Posted ty02

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板P1182数列分段II——二分答案相关的知识,希望对你有一定的参考价值。

题意:给定一列数,分成m段,使每段和的最大值最小。

 

  考虑二分最小段和size,答案显然满足单调性。可以在每次check中累加数列元素判断当前组的总和是否在size以内。由于序列元素均为非负整数,前缀和数组的值满足非严格单调递增,那么可以在前缀和上再套一个二分来优化暴力累加的过程。

  我不知道优化以后的复杂度怎么分析,反正它跑的快多了

代码:

  1. #include <iostream>  
  2. #include <cstdio>  
  3. #define maxn 100010   
  4. using namespace std;  
  5. int a[maxn], n, m;  
  6. long long s[maxn];  
  7. bool div(int sum)   
  8.     int cnt = 0;  
  9.     for (int i = 1; i <= n; )   
  10.         if (a[i] > sum) return false;  
  11.         int l = i, r = n;  
  12.         while (l < r)   
  13.             int mid = (l + r + 1) >> 1;  
  14.             s[mid] - s[i - 1] <= sum ? l = mid : r = mid - 1;  
  15.           
  16.         ++cnt, i = l + 1;  
  17.       
  18.     return cnt <= m;  
  19.   
  20. int main()   
  21. //  freopen("testdata-10.in", "r", stdin);  
  22.     ios::sync_with_stdio(0);  
  23.     cin >> n >> m;  
  24.     int l = 0, r = 0;  
  25.     for (int i = 1; i <= n; ++i)  
  26.         cin >> a[i], s[i] = a[i] + s[i - 1], l = max(l, a[i]);  
  27.     r = s[n];  
  28.     while (l < r)   
  29.         long long mid = (l + r) >> 1;  
  30.         if (div(mid))  
  31.             r = mid;  
  32.         else l = mid + 1;  
  33.       
  34.     cout << l;  
  35.     return 0;  
  36.  

 

以上是关于模板P1182数列分段II——二分答案的主要内容,如果未能解决你的问题,请参考以下文章

P1182 数列分段`Section II`

P1182 数列分段 Section II

数列分段II

洛谷 [P1182] 数列分段

P1182 数列分段`Section II`

1436:数列分段II