zoukankan      html  css  js  c++  java
  • RMQ算法使用ST表实现

    RMQ


    RMQ (Range Minimum Query),指求区间最小值。普通的求区间最小值的方法是暴力。

    对于一个数列:

    [A_1,~ A_2,~ A_3,~ cdots,~ A_n ]

    对于一个给定的区间([l, ~r], ~1≤ l ≤r ≤ n)(min {A_l, A_{l + 1}, cdots,A_r})的计算就是RMQ问题。

    此解法为( ext{Sparse-Table})解法,简称(ST)表。

    • 预处理:预处理为对数据进行(nlog n)的时间复杂度的处理

      (d(i, j ))(A_i, A_{i + 1}, cdots, A_{i + 2^j - 1})的最小值,即(d(i, j))的区间长度为(2^j),这里用到的是倍增的思想。

      (d(i, j - 1))(A_i, A_{1 + 1}, cdots, A_{i + 2^{j - 1}-1})的最小值,区间长度为(2^{j-1})

      同样地(d(i + 2^{j - 1}, j - 1))表示的是(A_{i + 2^{j-1}}, A_{i + 2^{j - 1} + 1}, cdots, A_{i + 2^{j-1} + 2 ^{j - 1} - 1 = i + 2^j - 1})

      所以显而易见:(d(i, j))可以表示为:

      [d(i,j) = min {d(i, j - 1), ~d(i + 2^{j - 1}, j - 1)} ]

    • 查询:

      (k)为满足(2 ^ k ≤ R - L+ 1)的最大整数,即(k = max{t~|~2^t ≤ R - L + 1, t in mathbb Z^+})

      同样地:(k =[ log_2 (R-L + 1)]),所以:(operatorname{Query}(L,R) = min {d(L,k),~d(R - 2^k + 1, k})

      查询的时间复杂度为(O(1))

    注意:由于每次(pow(2,x))非常浪费时间,在计算机内部二进制可以表示为:(1 << x)

    代码:

    namespace RMQ {
      	
      	void init(int n) {
          	for (int i = 1; i <= n; i ++) d[i][0] = a[i];
    				for (int j = 1; (1 << j) <= n; j ++) {
              	for (int i = 1; i + (1 << j) - 1 <= n; i ++) {
    								d[i][j] = min(d[i][j - 1], d[i + (1 << (j - 1))][j - 1]);
        }
              
    		int query(int l, int r) {
          	int k = log2(r - l + 1);
          	return min(d[l][k], d[r - (1 << k) + 1][k]);
        }
              
    }
    

    注意init中的循环顺序不能颠倒,显而易见,(j)的值,即区间的长度,必须由小到大。

  • 相关阅读:
    自定义ViewGroup基础巩固2---onMeasure()学习及综合实现圆形菜单
    Django自定义模板函数
    django迁移:全局、局部
    setup.py
    企鹅去北极熊家里玩
    python插入记录后获取最后一条数据的id
    清除浮动和解决塌陷
    html知识代码
    django模型:为已存在的表建立模型
    django模型:字段和选项
  • 原文地址:https://www.cnblogs.com/jeffersonqin/p/11210907.html
Copyright © 2011-2022 走看看