問題描述:
把乙個包含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...