(原文是发送到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群提问,微信酱会积极的解答的 ( ͡° ͜ʖ ͡°)
米娜桑,加油吧~