• RMQ


    RMQ是一种离线算法,通常用于求出区间【l,r】中的最大值或者最小值。

    显然这种问题用线段树是能解决的,我之前也一直用的线段树完成这题。

    RMQ,简称ST算法。 通过进行(nlogn)的预处理等操作,使询问的时间复杂度  达到  O(1),在此当然也蕴含着dp的思想。

    具体:

      设立一个数组dp【i】【j】  存着区间【i , i + 2^j-1】的最大值或者最小值,显然【i , i + 2^j-1】可以写成【i , i + 1<<j -1】

      同时区间【i , i + 2^j-1】  可以看成  【i,i+2^(j-1)-1】和  【i +2^(j-1), i + 2^j-1】的组成。       即转移方程:【i , i + 2^j-1】=max(【i,i+2^(j-1)-1】 ,【i +2^(j-1), i + 2^j-1】 )

        简化后dp【i】【j】=max(dp【i】【j-1】,dp【i+(1<<(j-1))】【j-1】)

    预处理:

    void init()
    {
        for (int i=1;i<=n;i++){
            cin>>dpmax[i][0];
            dpmin[i][0]=dpmax[i][0];
        }
        for (int j=1;(1<<j)<=n;j++){
            for (int i=1;(i+(1<<j)-1)-1<=n;i++){
                dpmax[i][j]=max(dpmax[i][j-1],dpmax[i+(1<<(j-1))][j-1]);
                dpmin[i][j]=min(dpmin[i][j-1],dpmin[i+(1<<(j-1))][j-1]);
            }
        }
        return ;
    }

    询问:

      通常给出,左边界 l 和 右边界 r 的确切值,求区间【l,r】的最大值或最小值

    此时我们只需要得到满足       2^k<=( r-l+1 )     的k的最大值

    然后把区间分为两个可以相交的区间,分别为【l , l+2^k-1】和 【r-2^k+1 , r 】      

         简化下就是:  dp【l】【k】 和 dp【r-(1<<k)+1】【k】

    int query(int l,int r)
    {
        int k=0,len=r-l+1;
        while ((1<<(k+1))<=len){
            k++;
        }
        return max(dpmax[l][k],dpmax[r-(1<<k)+1][k])-min(dpmin[l][k],dpmin[r-(1<<k)+1][k]);
    }

    练习题:  poj   3264  

      1.借鉴博客    求区间最值问题

      2.借鉴博客    求lca问题   (对于一棵树,求两个节点的最近公共祖先)

     

  • 相关阅读:
    迷の“良心”膜你赛总结*3
    bzoj1704/poj3276[Usaco2007 Mar]Face The Right Way自动转身机
    poj 1840 -- Eqs
    poj 3274 -- Gold Balanced Lineup
    poj 3349 -- Snowflake Snow Snowflakes
    poj 2442 -- Sequence
    BestCoder Round #1 1002 项目管理 (HDU 4858)
    BestCoder Round #1 1001 逃生 (HDU 4857)
    poj 1273 -- Drainage Ditches
    poj 1149 -- PIGS
  • 原文地址:https://www.cnblogs.com/q1204675546/p/11207227.html
Copyright © 2020-2023  润新知