关闭

st表

标签: 数据结构st表
214人阅读 评论(0) 收藏 举报
分类:

st表是用来查询数组中区间最值的。它应用的是动态规划的方法。

首先给一个数组a[0....n-1],长度为n,下标从0开始。现在要求区间[L,R]的最小值。

需要预处理出一个二维数组st[ i ] [ j ] ,它表示从下标i开始连续2^j个数中的最小值。边界条件为st[ i ] [ 0 ] = a[ i ],相当于从a[ i ] 开始的2^0 = 1个数的最小值,也就是a[ i ]。

动态规划的状态转移方程为:st[ i ][ j ] = min( st[ i ][ j - 1 ] , st[ i + 2^( j-1 )][ j - 1 ] )。

怎么理解这个转移方程?

现在的区间为[ i , i + 2^j -1 ] ,区间长度为 len  = 2^j。现在把这个区间分为两个等长区间1 : [ i , i + 2^(j - 1) - 1],区间长度为2^(j-1),区间2: [ i + 2^(j - 1) ,i + 2^j - 1],区间长度为2^j - 2^(j-1) = 2^(j-1)。这两个区间的最小值分别是st[ i ][ j - 1 ] ,st[ i + 2^(j-1) , j -1 ],也就是转移方程。

遍历的时候让i从n-1到0。


查询的时候,对于区间[L , R],k = floor(log2(L-R+1)),
将区间分解为两个长度为2^k的区间求最小值就行了。一个是从左边开始长度为2^k
,一个是从右边开始往左长度为2^k,显然这两个区间可以覆盖区间[L , R]。



源代码:

 

/*
st表:给一个数组A[n],动态查询区间[L,R]的最值
*/

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <cmath>
using namespace std;

const int maxn = 1e5;
int stTable[maxn][32];
int preLog2[maxn];

void st_prepare(int n,int *array){
  preLog2[1] = 0;
  for(int i = 2; i <= n; i++){
    preLog2[i] = preLog2[i-1];
    if( (1 << (preLog2[i]+1) ) == i)
    ++preLog2[i];
  }

  for(int i = n-1; i >= 0; i--){
    stTable[i][0] = array[i];
    for(int j = 1; (i+(1<<j) - 1) < n; j++)
    stTable[i][j] = min(stTable[ i ][ j-1 ],stTable[ i + 1<<(j-1) ][ j-1 ]);
  }
}

int query(int l,int r){
  int len = r - l + 1, k =preLog2[len];
  return min(stTable[l][k],stTable[r-(1<<k) + 1][k]);
}

int main(){
  int n = 10;
  int a[10] = {1,2,3,4,5,6,7,8,9,10};
  st_prepare(n,a);
  int l,r;
  while(cin>>l>>r){
    if(l==0 || r == 0)break;
    cout<<query(l-1,r-1)<<endl;
  }
  return 0;
}






0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:33612次
    • 积分:1074
    • 等级:
    • 排名:千里之外
    • 原创:76篇
    • 转载:1篇
    • 译文:2篇
    • 评论:0条
    最新评论