码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-08-16 23:03:51      阅读:115      评论:0      收藏:0      [点我收藏+]

标签:for   cst   max   序列   star   roc   lse   comm   ++   

题意:给定一列数,分成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——二分答案

标签:for   cst   max   序列   star   roc   lse   comm   ++   

原文地址:https://www.cnblogs.com/TY02/p/11366562.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!