二分法解決最大值最小化問題

2021-10-01 15:37:35 字數 1369 閱讀 7072

問題描述:

把乙個包含n個正整數的序列劃分成m個連續的子串行。設第i個序列的各數之和為s(i),求所有s(i)的最大值最小是多少?

例如序列1 2 3 2 5 4劃分為3個子序列的最優方案為 1 2 3 | 2 5 | 4,其中s(1),s(2),s(3)分別為6,7,4,那麼最大值為7;

如果劃分為 1 2 | 3 2 | 5 4,則最大值為9,不是最小。

演算法思路1

要解決最大值最小化的問題,基本思路就是選取任意乙個範圍(輸入陣列的最大值到陣列所有元素的和),然後在這個範圍內進行二分法,範圍的中間值mid值是否能夠被分為m個部分。

設s[i]中最大值的最小值是x,則很容易想出,x能取得最大值為全序列之和sum,x能取的最小值為a[i]中的最大值max,即x的取值範圍為[max,sum]。然後要做的事情就是在[max,sum]中找到x,根據習慣尿性,紅果果的二分查詢。

時間複雜度

二分所有可行解,然後掃瞄一次原序列。

掃瞄原序列,即是找出滿足題意的最大值即可,所以複雜度是o(n)

二分複雜度是log(m),所以求解複雜度是n*logm

**

#include

"stdafx.h"

//#include

#include

#include

#include

#include

#include

#include

#include

#define mx 1000005

#define ll long long

#define lson l,m,rt<<1

#define rson m+1,r,rt<<1|1

using

namespace std;

int a[mx]

;int n, m;

// 掃瞄一次原序列,複雜度是o(n)

bool

judge

(int x)

if( k > m -1)

sum +

= a[i];}

return

true

;// 返回true,說明隔板的數目<=m-1,說明了x太大,需要讓right = mid

}// 二分複雜度是log(m)

intbs

(int l,

int r)

return l;

// 跳出迴圈的時候,l = 為s(i)中所有最大值的最小值 = r,可以返回r或者l的值

}int

main()

cout <<

bs(max, sum)

<< endl;

}return0;

}

↩︎

二分法解決最大值最小化問題

把乙個包含n個正整數的序列劃分成m個連續的子串行。設第i個序列的各數之和為s i 求所有s i 的最大值最小是多少?例如序列1 2 3 2 5 4劃分為3個子序列的最優方案為 1 2 3 2 5 4,其中s 1 s 2 s 3 分別為6,7,4,那麼最大值為7 如果劃分為 1 2 3 2 5 4,則...

基礎演算法 二分法 最大值最小化

有乙個序列,將其劃分成3個連續的子串行s 1 s 2 s 3 每個子串行最少有乙個元素,要求使得每個子串行的和的最大值最小 輸入 622 3451 輸出 來自 大佬傳送門 include include using namespace std define n 10 define inf 1000 ...

二分 最小化最大值

注意答案的二分性質,必須要滿足在滿足給定條件的所有情況的時候都滿足要求才能更新ans。include using namespace std typedef long long ll inline ll in while c 0 c 9 res res 10 c 48,c getchar retur...