【問題描述】
高考結束後,同學們大都找到了乙份臨時工作,渴望掙得一些零用錢。從今天起,matrix67將連續工作n天。每一天末他可以領取當天及前面若干天裡沒有領取的工資,但他總共只有m次領取工資的機會。matrix67已經知道了在接下來的這n天裡每一天他可以賺多少錢。為了避免自己濫用零花錢,他希望知道如何安排領取工資的時間才能使得領到工資最多的那一次工資數額最小。
注意:matrix67必須恰好領工資m次,且需要將所有的工資全部領走(即最後一天末需要領一次工資)。
【輸入格式】
第一行輸入兩個用空格隔開的正整數n和m。
以下n行每行乙個不超過10000正整數,依次表示每一天的薪水。
【輸出格式】
輸出領取到的工資的最大值最小是多少。
【輸入樣例】
7 5
100
400
300
100
500
101
400【輸出樣例】
【資料範圍】
1<=n<=100000
1 <=m<=n
【樣例解釋】
採取下面的方案可以使每次領到的工資不會多於500。這個答案不能再少了。
100 400 300 100 500 101 400 每一天的薪水
<——1 <——-2 <—3 <—4 <—5 領取工資的次數
500 400 500 101 400 領取到的工資
題目大意:給你一段序列a,要求你在該序列中找出m個互不重疊且包含完a中所有元素的連續子串行使得各連續子串行的最大值最小。
演算法:二分答案(最大值最小問題)。
典型的最大值最小問題,所以想到二分答案,在區間[0,10^9]內二分猜最小值x。設check(m)來檢查m是否可行。check(m)寫法為:設sum為當前一段選擇連續子串行中的a的值的總和,ret為a中還剩餘的未領的工資總額,計數變數cnt=0。設游標j,當j<=n && cnt小於m(因為在最後乙個位置必須選)時,如果有sum+a[j]<=m,j++,累加sum,累減ret,此時就必須在第j天領一次工資(因為在後面一天領了工資就會使得最大值超過m)計數變數cnt++,更新sum=0。如果迴圈完了,也就是說已經領了m次工資,如果還沒有領完(ret>0)則說明m不符合題意。否則m可行。
#include
#include
#include
#include
#include
#include
#define maxn 100010
using
namespace
std;
typedef
long
long ll;
int n,m;
int a[maxn],sum[maxn];
/*void ready()
*/bool check(int mid)
if(ret>0)return
0; return1;}
int main()
cout
0;}
TYVJ 1359 收入計畫(二分)
一開始是一眼看出是二分的,因為這裡有單調性,因為取錢是一次取完並且是連續的。所以最優取法就是準備達到某個價值再取。最優裡邊包含了次優,也就是取不到m次我就能取完就一定能夠取m次能夠取完,只要在取法那裡隨便取就行了,保證不超過這個某個價值 於是我們可以二分這個價值,看看能不能最優法取完並且次數小於m。...
運輸計畫 二分答案 樹上差分
p2680 運輸計畫 附贈樣例圖 首先容易想到二分答案,將求解問題轉換為判定,並且注意到答案顯然具有單調性。然後我們考慮如何快速判定。先預處理出所有計畫路徑長 dis i 表示根節點到節點 i 的距離,dis u dis v 2 times dis lca u,v 即為樹上 u,v 路徑長 對於那些...
NOIp複習計畫 二分答案
bzoj 1614 usaco2007 jan telephone lines架設 線 二分答案,把小於k的設成0否則為1,然後spfa判斷。include using namespace std const int maxn 20005 int h maxn to maxn 1 nx maxn 1...