巧克力 二分
[Description]
现在有一块1*1*N 的巧克力(每个1*1*1 的部分有一个营养值Ai),想分给K 个小朋友,并且每个小朋友必须得到一整块,即最终只能分成K 块,每个小朋友所得到的营养值即为得到巧克力每部分的营养值之和。
这几个小朋友的自尊心很强,尤其是不允许分得营养值最大的那个人所得的营养值太大。所以,为了照顾好他们,你必须使分得营养值最大的那个人的营养值尽量小。
[Input]
第1 行:两个整数N 和K
第2 行:N 个整数Ai,相邻整数用空格隔开
[Output]
一行,分得最多的那个人的最少巧克力
[Sample 1]
chocolate.in |
chocolate.out |
5 2 2 1 3 4 5 |
9 |
样例解释:有如下分法
2 | 1 3 4 5 -> 2 和13 -> max=13
2 1 | 3 4 5 -> 3 和12 -> max=12
2 1 3 | 4 5 -> 6 和9 -> max=9
2 1 3 4 | 5 -> 10 和5 -> max=10
再对所有取小min=9
[Hit]
对于30%数据 N <= 30, K <= 10
对于100%数据 N <= 100000, K <= N, Ai <= 10^9
第一眼看到这题,我是懵逼,后来知道这题使用二分,再结合它只能整块分的性质,我们就可以写出怎么检查的过程,然后这题就没了。
代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define ll long long #define il inline #define db double using namespace std; il int gi() { int x=0,y=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') y=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*y; } il ll gl() { ll x=0,y=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') y=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*y; } int n,k; ll cho[100045]; il bool check(ll x) { int sum=0; ll now=0; for(int i=1;i<=n;i++) { now+=cho[i]; if(now>x) { sum++; now=cho[i]; } } sum++; if(sum<=k) return 1; else return 0; } ll ans; void hzr(ll l,ll r) { if(l==r) return; ll m=(l+r)>>1; if(check(m)) { ans=m; hzr(l,m); } else { hzr(m+1,r); } } int main() { freopen("chocolate.in","r",stdin); freopen("chocolate.out","w",stdout); n=gi(),k=gi(); for(int i=1;i<=n;i++) cho[i]=gl(); hzr(1,100000000000000); printf("%lld\n",ans); return 0; }
PEACE