• 每周算法讲堂,二分法


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

    米娜桑,加油吧~

  • 相关阅读:
    Hybrid APP基础篇(三)->Hybrid APP之Native和H5页面交互原理
    Hybrid APP基础篇(二)->Native、Hybrid、React Native、Web App方案的分析比较
    Hybrid APP基础篇(一)->什么是Hybrid App
    JavaScript筑基篇(一)->变量、值与对象
    深入Node.js的进程与子进程:从文档到实践
    深入Node模块Buffer-学会操作二进制
    深入Nodejs模块fs
    刷《一年半经验,百度、有赞、阿里面试总结》·手记
    Asp.Net Core 轻松学-被低估的过滤器
    css精灵图&字体图标
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5212649.html
Copyright © 2020-2023  润新知