st表

来源:互联网 发布:百分百营销软件流量 编辑:程序博客网 时间:2024/04/17 06:29

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
原创粉丝点击