loj10014數列分段二
阿新 • • 發佈:2020-11-21
10014.「一本通 1.2 練習 1」數列分段 II
題目描述對於給定的一個長度為 n 的正整數數列 A ,現要將其分成 m 段,並要求每段連續,且每段和的最大值最小。
例如,將數列 4,2,4,5,1 要分成 3 段:
若分為 [4,2][4,5][1] ,各段的和分別為 6,9,1 ,和的最大值為9 ;
若分為 [4][2,4][5,1] ,各段的和分別為 4,6,6 ,和的最大值為 6;
並且無論如何分段,最大值不會小於6 。
所以可以得到要將數列 4 2 4 5 1 要分成 3 段,每段和的最大值最小為 6 。
輸入格式第行包含兩個正整數 n,m;
第行包含 n 個空格隔開的非負整數 A_i,含義如題目所述。
僅包含一個正整數,即每段和最大值最小為多少。
樣例 輸入複製5 3
4 2 4 5 1
輸出複製
6
資料範圍與提示
對於100% 的資料,有n<=1e5,m<=n,A_i 之和不超過 1e9 。
________________________________ 二分答案 ________________________________1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const intView Codemaxn=1e5+10; 5 ll sz[maxn]; 6 ll n,m; 7 ll l,r,ans; 8 bool pd(ll x) 9 { 10 ll sm=0,js=1; 11 for(int i=1;i<=n;++i) 12 { 13 if(sm+sz[i]>x) 14 { 15 js++; 16 sm=0; 17 } 18 sm+=sz[i]; 19 } 20 return js<=m; 21 } 22 int main()23 { 24 scanf("%lld%lld",&n,&m); 25 for(int i=1;i<=n;++i) 26 { 27 scanf("%lld",sz+i); 28 r+=sz[i];l=max(l,sz[i]); 29 } 30 31 while(l<=r) 32 { 33 ll mid=(l+r)>>1; 34 if(pd(mid))ans=mid,r=mid-1; 35 else l=mid+1; 36 } 37 cout<<ans; 38 return 0; 39 }