蜡烛(e.cpp)

题目描述:

奶牛bessie有n根蜡烛,第i根蜡烛的长度是h[i]。bessie最近刚上完小学,只会加减法。它想知道它的n根蜡烛最多能用多少个晚上。由于bessie比较胆小,因此它每天晚上需要点燃c根蜡烛。每根被点燃的蜡烛,它燃烧一个晚上会使得它的长度减少1。一旦蜡烛的长度变成0,那么该根蜡烛就用完了。如果第i个晚上bessie发现蜡烛不够用了,那么bessie最多就只能用i-1个晚上。

Bessie想知道,它该如何选择每个晚上点燃哪些蜡烛,使得它的n根蜡烛能用尽量多的晚上。输出最多能用多少个晚上。

输入格式

第一行:两个整数n,c,1 <= n,c<=1000000

第二行:n个整数,第i个整数表示第i根蜡烛的长度h[i]。1 <= h[i] <= 1000000

输出格式

一个整数,总共最多能用多少个晚上

数据范围

对于 30% 的数据, 1 <=n,c<=1000。

对于 100% 的数据, 1 <=n,c<=10^6。

样例输入

3 3

2 2 2

样例输出

2

这题出得非常的好,想解决这题,要利用前缀和,数组下标,二分法,所以我一开始的思路是这样的

#include <bits/stdc++.h>
using namespace std;
long long n,m,x,p,k,l,r,a[10000009],b[10000009],c[10000009],mid,sum;
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>x;
        sum+=x;
        k=max(k,x);
		a[x]++;
	}
	for(int i=1000000;i>=1;i--)b[i]=b[i+1]+a[i];
	for(int i=1;i<=1000000;i++)c[i]=c[i-1]+a[i]*i;
	int l=0;
	r=INT_MAX;
	for(;;)
	{
		mid=(l+r)/2;
        if(mid>k)p=c[k]/mid;
		else p=b[mid]+c[mid-1]/mid;
		if(p>=m)l=mid;
		if(p<m)r=mid;
		if(l+1==r)break;
	}
    sum=l;
	cout<<sum;
	return 0;
}

但只拿了80分,后来研究来研究去,原来是r的值没有取对,正确代码如下

#include <bits/stdc++.h>
using namespace std;
long long n,m,x,p,k,l,r,a[9999999],b[9999999],c[9999999],mid,sum;
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>x;
        sum+=x;
        k=max(k,x);
		a[x]++;
	}
	for(int i=10000000;i>=1;i--)b[i]=b[i+1]+a[i];
	for(int i=1;i<=10000000;i++)c[i]=c[i-1]+a[i]*i;
	l=0;
	r=1e12+1;
	for(;;)
	{
		mid=(l+r)/2;
        if(mid>k)p=c[k]/mid;
		else p=b[mid]+c[mid-1]/mid;
		if(p>=m)l=mid;
		if(p<m)r=mid;
		if(l+1==r)break;
	}
    sum=l;
	cout<<sum;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值