1. 程式人生 > 實用技巧 >YbtOj例題:二分1 數列分段

YbtOj例題:二分1 數列分段

http://noip.ybtoj.com.cn/contest/14/problem/1

雖然這道題是例題,但是它非常的經典。所以我決定寫一寫。

通常,求解”最大值最小“或”最小值最大“一類的問題,都會用到二分演算法。但僅憑這一個條件無法確定使用二分演算法,下面舉幾個栗子

1.

(這是本題)

總的分組數目有限制,二分有判定條件,可以二分。 答案轉化為二分判定

2.

洛谷P4047部落劃分

部落總數有限制,可以二分。 答案轉化為二分判定

3.

洛谷P4447 [AHOI2018初中組]分組

雖然總的組數沒有限制,但我們可以構造出一個單調上升的序列,p[x]表示第x組接下來需要接上的數的大小,它是單調遞增的,我們可以二分 二分查詢

4.

洛谷P1080國王遊戲

這道題就不能二分,因為總錢數沒有限制,我們也構造不出一個單調的幫助我們解題的序列。

回到這道題

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5, inf = 0x3f3f3f3f;
int n, m, a[N];
int l, r = 0;
bool check(int x) {
    int s = 0, cnt = 1;
    for (int i = 1; i <= n; i++) {
        if (s + a[i] <= x)
            s 
+= a[i]; else { cnt++; s = a[i]; } } return cnt <= m; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); l = max(l, a[i]); r += a[i]; } while (l < r) {
int mid = l + r >> 1; if (check(mid)) r = mid; else l = mid + 1; } printf("%d", l); return 0; }