###### RMQ问题的ST算法

ST(Sparse Table)算法的基本思想是，预先计算从起点A[i]开始长度为2的j次方(j=0,1...logn)的区间的最小值，然后在查询时将任何一个区间A[i..j]划分为两个预处理好的可能重叠的区间，取这两个重叠区间的最小值。

ST算法预处理阶段的复杂度为O(nlogn)，查询阶段的复杂度为O(1)。

/**
 * 
 * Using ST(Sparse Table) algorithm to solve RMQ problem
 * time complexity: <O(nlogn),O(1)>
 * 
 *  
 * Copyright (c) 2011 ljs (http://blog.csdn.net/ljsspace/)
 * Licensed under GPL (http://www.opensource.org/licenses/gpl-license.php) 
 * 
 * @author ljs
 * 2011-08-02
 *
 */
public  class RMQ_ST {

    //ST: O(nlogn) for preprocessing
    public int[][] preprocess(int[] A){
        int n = A.length;
        //floor value
        int maxJ=(int)(Math.log(n)/Math.log(2));

        int[][] M = new int[n][maxJ+1];

        //initial condition for dynamic programming: the RMQ for interval length=1
        for (int  i = 0; i < n; i++)
              M[i][0] = i;

        //dynamic programming: compute values from smaller(j=1) to bigger intervals
        for (int  j = 1; j<=maxJ; j++){
            for (int  i = 0; i + (1 << j) - 1  < n; i++){
                int nexti = i + (1  << (j - 1));
                if (A[M[i][j - 1]] <= A[M[nexti][j - 1]])
                    M[i][j] = M[i][j - 1];
                else
                    M[i][j] = M[nexti][j - 1];
            }
        }
        return M;
    }

    //ST: O(1) for querying
    public int query(int[] A,int[][] M,int i,int  j){
        if(j<i){
            //swap i and j
            int tmp=i;i=j;j=tmp;
        }
        int k = (int)(Math.log(j-i+1)/Math.log(2));
        //the first interval
        int mina = M[i][k];
        int minb = M[j-(1<<k)+1][k];
        if(A[mina]<=A[minb])
            return mina;
        else
            return minb;
    }

    public static void  main(String[] args) {        
        int[] A=new int[]{0,1,2,3,7,1,9,2,8,6};
        RMQ_ST st = new RMQ_ST();
        int[][] M = st.preprocess(A);


        System.out.format("%n***********************%n");       
        int i=3,j=7;        
        int min = st.query(A,M, i,j);
        System.out.format("RMQ for A[%d..%d]: A[%d]=%d", i,j,min,A[min]);

        System.out.format("%n***********************%n");
        j=3;i=7;    
        min = st.query(A,M, i,j);
        System.out.format("RMQ for A[%d..%d]: A[%d]=%d", i,j,min,A[min]);

        System.out.format("%n***********************%n");
        for(int x=0;x<A.length;x++){
            for(int y=0;y<x;y++){
                System.out.format("    ");
            }
            for(int y=x;y<A.length;y++){
                int p = st.query(A,M,x,y);
                System.out.format(" %d/%d",A[p],p);
            }
            System.out.println();
        }   
    }

}

#### 理解RMQ问题和ST算法的原理

2014-05-25 13:16:26

#### RMQ问题的ST算法详解

2012-10-31 16:29:08

#### RMQ--ST表算法理解

2016-07-21 11:59:59

#### hihoCoder_#1068_RMQ-ST算法

2015-08-05 16:35:34

#### 【算法】最近公共祖先之在线算法(RMQ-ST)

2016-05-25 14:34:43

#### RMQ算法分析

2014-08-06 18:48:20

#### 后缀数组倍增算法实现

2012年09月02日 2KB 下载

#### RMQ（模板 ST 区间最值，区间频繁次数）

2014-11-03 22:36:11

#### RMQ的ST写法和线段树写法两种姿势

2013-11-09 12:20:21

#### ST表算法详解

2017-08-25 08:21:55

RMQ问题的ST算法