• RMQ 区间最值问题


    今天学弟在群里直播讲课,讲了RMQ,以前摸鱼太多这个题目并没看出来是啥,然后就去凑了个热闹。

    RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大)值,也就是说,RMQ问题是指求区间最值的问题。

    对于这个问题,区间最值,多次查询,我第一反应是线段树,也确实是线段树最值问题的基础模型,线段树博客其他文章中有,这里不单独拿出来了。

    学弟讲这个题目,讲了3中方法暴力、动态规划,ST(Sparse Table)

    暴力:没什么好说

    int RMQ(int A[], int mi, int ma) {
    	int rt_max = -INF, rt_min = INF;
    	for(int i=mi; i<=ma; i++) {
    		rt_max = max(A[i], rt_max);
    		rt_min = min(A[i], rt_min);
    	}
    	return {...};
    }

    动态规划:

    dp[i][j]维护为从i到j的最大值或最小值,状态转移方程即:

    dp[i][j]=max(dp[i][j-1],dp[j][j]);

    这样在最开始将所有的值全部进行预处理,每次查询只要查询dp[i][j]的值,就能直接得到A[i]-A[j]的最大值和最小值:

    int dp[MX][MX];
    void init_RMQ(int A[], int n) {
    	for(int i = 0; i < n; i++) {
    		dp[i][i] = A[i];
    	}
    	for(int i = 0; i < n; i++) {
    		for(int j = i + 1; j < n; j++) {
    			dp[i][j] = max(dp[i][j-1], dp[j][j]);
    		}
    	}
    }
    

    ST算法:

    这是一种用二分优化的DP,dp[i][j]为从i开始到i+2^j-1的最值

    dp[i][0] = max(A[i] to A[i + (2^j) - 1]) ...A[i]			len = 2^0 = 1 
    dp[i][1] = max(A[i] to A[i + (2^j) - 1]) ...A[i],A[i+1];   		len = 2^1 = 2
    dp[i][2] = max(A[i] to A[i + (2^j) - 1]) ...A[i],A[i+1],A[i+2],A[i+3]  	len = 2^2 = 4
    dp[i][3] = .... len = 2^3 = 8 ...

    dp[i][j]的状态转移方程如下

    dp[i][j] = max(dp[i][j - 1], dp[i + 2^(j-1)][j - 1]);
    void init_RMQ(int A[], int n) {
    	for(int i = 1; i <= n; i++) {
    		dp[i][0] = A[i];
    	}
    	for(int j = 1; (1<<j) <= n; j++) {
    		for(int i = 1; (i + (1<<j) - 1) <= n; i++) {
    			dp[i][j] = max(dp[i][j-1], dp[i + (1<<(j-1))][j-1]);
    		}
    	}
    }

    当我们需要查询A[1]-A[7]的时候,查询的长度为7,我们则可以查询两个长度为4的区间来确定这个区间的最值,而log2(4) = 2

    转化成dp则为只需要查询dp[1][2]和dp[7-4+1][2]的两个的最值比较即可:max(dp[1][2],dp[4][2])

    int Query_max(int l,int r) {
    	int k= log2(r - l + 1);
    	return ( max(dp[l][k], dp[r - (1<<k) + 1][k]));
    }
    

      

  • 相关阅读:
    function 基础运用
    js基础知识2
    JavaScript的一些基础知识
    CSS3中2D3D转换、过渡、动画总结
    css的一些基础属性
    响应式布局和移动端开发
    css3动画
    美化盒子以及bootstrap的简单了解
    利用JS的双重for循环实现九九乘法表
    js练习:金字塔正星星与倒星星
  • 原文地址:https://www.cnblogs.com/HDMaxfun/p/12189945.html
Copyright © 2020-2023  润新知