吃巧克力

最坑的一道二分题

巧克力要全部吃完,余下的巧克力默认放在最后一天吃。

(check) 函数写得不够熟练啊!!!
继续努力。

#include<iostream>
#include<cstring>
#include<cstdio>
#define LL long long
#define mid ((l+r)>>1)
using namespace std;
const LL N = 50005;
LL n,m,a[N],ans[N],l,r,anst;
inline LL read()
{
	char c=getchar();
	LL ans=0,w=1;
	while((c<'0'||c>'9')&&c!='-') c=getchar();
	if(c=='-') { w=-1; c=getchar(); }
	while(c>='0'&&c<='9')
	{ ans=ans*10+c-'0'; c=getchar(); }
	return ans*w;
}
bool check(LL u)
{
	LL tot=0,last=0,cnt=0,ansp=0;
	while(tot<m)
	{
		last=last/2; ansp=0;
		while(ansp+last<u)
		{
			++cnt; ansp+=a[cnt];
			if(cnt>=n) break;
		}
		last=ansp+last;
		if(last>=u) ++tot;
		else break;
	//	if(cnt>=n) break; 直接break 会导致接下来一直减半,但还是满足条件的情况漏掉 
	}// 还好这样的点只有一个  
	if(tot>=m) return true;
	return false;
}
void print(LL u)
{
	LL tot=0,last=0,cnt=0,ansp=0;
	while(tot<m)
	{
		last=last>>1; ansp=0;
		while(ansp+last<u) ansp+=a[++cnt],printf("%lld
",tot+1);
		last=ansp+last;
		++tot;
	}
	if(cnt<n)// 大坑点 有意思么 
	 for(LL i=cnt+1;i<=n;i++)//
	  printf("%lld
",m);// 
	return ;
}
int main()
{
	n=read(); m=read();
	for(LL i=1;i<=n;i++)
	 a[i]=read(),r+=a[i];
	while(l<=r)
	{
		if(check(mid)) { anst=mid, l=mid+1; }
		else r=mid-1;
	}
	printf("%lld
",anst);
	print(anst);
	return 0;
}
原文地址:https://www.cnblogs.com/karryW/p/10877718.html