巧用二分法

题意:有N个城市,每个城市有Ai个人。
现在要开始投票,每个人有一张票。
作为领导者,你有B个箱子,你必须要将这B个箱子分发到N个城市去,每个城市至少需要一个箱子。
每个人都必须要投票,不能弃票,也就是说要把票丢进箱子里去(每个城市有Ai张票)。
现在问你,怎么分配这B个箱子才能使这些所有箱子里中票数最大的那个箱子里的票最少?
1<=N<=500,000,N<=B<=2,000,000,1<=Ai<=5,000,000。

思路:若每个城市都先分得一个箱子,那么目前的答案就是max(Ai(1<=i<=n))。所以,我们必须要给最大值的那个城市还需要至少分配一个箱子,那么答案肯定不再是那个城市(也有可能有某个城市的人数跟该城市人数一样,那么答案还是没变)。
接下来如果你还有箱子,你肯定要给次大值的那个城市至少再分配一个箱子;
接下来如果你还有箱子,你肯定要给次次大值的那个城市至少再分配一个箱子;
接下来如果你还有箱子,你肯定要给次次次大值的那个城市至少再分配一个箱子;
接下来如果你还有箱子,你肯定要给次次次次大值的那个城市至少再分配一个箱子;
。。。
直到什么时候呢?
直到原先那个最大值城市的票数的一半(奇数需要再加1)大于等于了你刚刚从大到小排列的城市的那个票数,为什么?
因为那个城市的后面的票数肯定小于等于那个城市,那么这些城市中没有一个票数是比那个最大值城市的票数的一半还要大,也就是说当前状态下,所有城市中,原先那个最大值城市的票数的一半成了当前最大值。

解题:你想到了什么?——二分!
我们二分票数,票数范围是1到某个城市的最大票数。
记l=1, r=max,那么mid=(1+max)/2;
假设mid就是答案,那么我们需要统计一下一共需要几个箱子。

int num = 0;

for (int i = 1; i <= n; i++)

{

if (a[i] % mid) num += a[i] / mid + 1;

else num += a[i] / mid;

}

那么最后需要num个箱子,但是我们有B个箱子,所以需要比较一下。
如果num>B,说明我们需要的箱子不够,也就是说票数不小于mid值的那些城市中有些城市分不到足够的箱子,所以,我们的最终答案肯定是大于num的。那么二分范围落在[mid + 1, max]。
如果num<=B,说明我们需要的箱子很够,也就是说票数不小于mid值的那些城市中所有城市都能分到足够的箱子,所以,我们的最终答案肯定是小于等于num的。那么二分范围落在[1, mid]。
然后继续二分,直到最终的范围l>=r为止结束。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值