zoukankan      html  css  js  c++  java
  • 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]));
    }
    

      

  • 相关阅读:
    全栈程工程师
    月薪8000的程序员和月薪2万的程序员差别在哪里?
    原型中的访问
    关于 基本类型和复合类型 用== 判断的小问题
    使用原型解决构造函数问题
    前端工程师学习路线 --书籍
    程序员成长之路
    GIT学习(1) Pull和Fetch
    OO面向对象编程:第四单元总结及课程总结
    OO面向对象编程:第三单元总结
  • 原文地址:https://www.cnblogs.com/HDMaxfun/p/12189945.html
Copyright © 2011-2022 走看看