每周算法讲堂,二分法

(原文是发送到UESTCACM微信的,所以欢迎大家关注哦~

大家好,我是萌萌的微信酱!

又到了一周一度难得的周三了哦,你们找到女朋友了吗?喵。

另外你们有没有想我呢?

众人:没有。

呜呜呜呜呜……

(擦干眼泪。)

这周呢,我要讲的算法是二分法,至于为什么要讲这个算法呢,我才不会告诉你们是因为这周的每周一题就是二分呢。

引入一道例题:

Block Towers(来源codeforces 8VC Venture Cup 2016 - Elimination Round C题)
题意:

你需要找n个2的倍数,m个3的倍数,要求所有数都不一样

你的目的是使得其中最大的数最小,然后问你这个数是多少呢?

(0 ≤ n, m ≤ 1 000 000, n + m > 0)

喵,题意讲完了~

你们知道怎么做吗?

只见迅雷不及掩耳盗铃之势,小郭同学一看到这道题,大呼:“这不是傻X题吗?我会做了!”

小郭说:“这道题贪心就好了,由于是2和3之间的关系,肯定3得优先排前面,我先把3分配完,然后再弄2就好了!”

小郭三下五除二就把代码写完,submit!

duang,Wrong answer on pretest 4。

哼,这周的主题就是二分,怎么能够让你贪心贪过去呢?(一脸傲娇

第4个数据是 4 2,贪心的话,答案是10,但实际答案可以是9.

这道题,如果正面去贪心的话,情况多多,比较麻烦,而且写着好累啊。

那么我们怎么做呢?

我们首先第一步,认识到这个答案是具有单调性的!

如果T这个值是符合答案的,那么存在To>T,To显然也是符合答案的。

因为To范围内的数显然比T多,而且To完全可以和T选取一模一样的数出来。

反之,如果T是不符合答案的,如果To<T,显然To也是不符合答案的。

然后我们就可以开始二分答案咯。

我们把问题转换为,给你T,问你T范围内,是否能够分离出n个2的倍数,和m个3的倍数,并且这些数都是不一样的呢?

只听喵的一声,沈宝宝说他会做了!

沈宝宝说:“我们可以知道,T范围内,是2的倍数的数有T/2个,是3的倍数的有T/3个,即是2又是3的倍数的数,有T/6个,那么只要(max(0,n-(T/2-T/6))+max(m-(T/3-T/6),0))<=T/6就好了!" 。

回答正确!奖励一颗糖!

我们就二分答案,不断check就好了。

我们首先找到答案的下界,l = 0,以及答案的上界r = 3*1000000。

然后我们不断check((l+r)/2),如果(l+r)/2是符合答案的,那么根据单调性,显然[(l+r)/2,+∞)这个范围,都是符合答案的,那么我们令r = mid。如果(l+r)/2不符合答案,同理,根据单调性,(-∞,(l+r)/2]都是不符合答案的,我们就令l=mid。

然后这样不断的进行check,直到l > r的时候,这样我们就能找到那个不符合和符合的分界线了~

这条分界线,显然就是答案咯。

喵,每一次check的时候,时间复杂度是O(1),我最多check logn次,所以二分的总时间复杂度是O(logn)的,完全可以接受。

于是,我得到了Accepted。

喵喵喵,二分就讲完了,你们懂了吗?

如果不懂就给微信酱留言哦,或者在QQ群提问,微信酱会积极的解答的 ( ͡° ͜ʖ ͡°)

米娜桑,加油吧~

posted @ 2016-02-24 13:35  qscqesze  阅读(1178)  评论(0编辑  收藏  举报