zoukankan      html  css  js  c++  java
  • 倍增答案

    众所周知有一种很实用的算法叫做二分答案。

    二分答案可以解决一些答案具有单调性的问题。

    比如说:洛谷 P2678 跳石头,这是再基本不过的二分答案了吧?

    答案满足单调性意为,如果让你找的答案为满足某种条件的最小值x,那么大于x的所有值也都合法,小于x的所有值都不合法。

    或者是,如果让你找的答案为满足某种条件的最大值x,那么小于x的所有值也都合法,大于x的所有值都不合法。

    合法或不合法的判定在于check函数的返回值。

    这个二分答案的算法一般是这样实现的:(以跳石头为例)

    int ans;
    int ll=0;
    int rr=maxl;
    while(ll<=rr)
    {
        int mid=(ll+rr)/2;
        if(check(mid))
        {
            ll=mid+1;
            ans=mid;
        }else
        {
            rr=mid-1;
        }
    }

    最后求出来的ans就是答案。

    可以看出,最短跳跃距离很小的时候都能被满足,所以题目要求我们求一个最大值。

    而且满足单调性:比某个值大的距离都不能被满足,小于等于某个值的距离都可以被满足。

    这就是单调性。

    因为满足单调性,所以用二分答案就行。

    但是经过长时间的应用我发现二分答案有一些小缺点:l、r的边界判断(即while循环的退出条件)很烧脑。

    又联想到倍增LCA的算法实际上也是一个类似二分答案的过程。

    比LCA浅的节点都是公共祖先,比LCA深的节点都不是公共祖先,我们要在这里找一个最近(也就是最深)公共祖先(LCA)。

    但是这里我们利用数的二进制表示来倍增,而并没有二分答案。

    所以我想到了倍增答案的算法,类似倍增LCA。

    还是以跳石头为例:

    int ans=0;
    for(int i=30;i>=0;i--)
    {
        if(check(ans|(1<<i)))ans|=(1<<i);
    }

    这样之后,ans的值就是答案。

    可以看出代码与倍增LCA很相似。

    正确性也是毋庸置疑。

    只要i这一位加上去还合法,那就加上去。

    最后肯定得到一个合法且最大的值,也就是合法的最大值。

    那么如果大的值都合法,让我们求一个合法的最小值呢?

    合法的最小值不就是不合法的最大值+1嘛。

    这样我们求出不合法的最大值就行了。

    int ans=0;
    for(int i=30;i>=0;i--)
    {
        if(!check(ans|(1<<i)))ans|=(1<<i);
    }
    ans=ans+1;

    倍增答案大法好!

    如果各位大佬发现了什么bug请在底下评论哦~

    谢谢!

  • 相关阅读:
    Django 项目试炼blog(8) -- 评论树的显示
    Django 项目试炼blog(7) -- 文章详情页2 -- 前端样式的继承与楼评论显示
    Django 项目试炼blog(6) -- 文章详情页1 -- 点赞功能
    Django 项目试炼blog(5) -- 个人站点的搭建
    Django 项目试炼blog(4)--blog主页的搭建以及admin的使用
    Django 项目试炼blog(3)--基于Form组件ajax用户注册
    Django 项目试炼blog(2)--用户登陆验证
    Django 项目试炼blog(1)
    Django 基于form与ajax发送文件
    Django 分页器制作
  • 原文地址:https://www.cnblogs.com/cervusy/p/9609213.html
Copyright © 2011-2022 走看看