2017-08-26 21:44:45
writer:pprp
RMQ问题就是区间最大最小值查询问题;
这个SparseTable算法构造一个表,F[i][j] 表示 区间[i, i + 2 ^ j -1]的最大或者最小值
ST分为两个部分
1、nlogn的预处理
预处理主要用到了动态规划,二分区间每个区间长度为 2 ^ (j -1)找到一个递推关系;
F[i][j] &#61; min(F[i][j - 1],F[i &#43; (1 <<(j - 1))][j - 1]);
2、查询部分更为巧O(1)得到询问结果
对于任意一个区间【n,m】来说&#xff0c;可以将其划分为两个以上区间的和
【m,n】 &#61; 【m, m&#43;2^k-1】 &#43; 【n-2^k-1,n】
其中k &#61; log2(n-m&#43;1)
实现的代码如下&#xff1a;
/*
&#64;theme:ST表&#xff08;sparse table&#xff09;稀疏表
&#64;writer:pprp
&#64;declare:用动态规划的思想来解决RMQ问题&#xff1b;
&#64;date:2017/8/26
*//*方程
F[i,j]:区间[i,i &#43; 2^j - 1]的最小值&#xff0c;此时区间长度为2^j
转移方程&#xff1a;F[i,j] &#61; min(F[i,j - 1],F[i &#43; 2^(j - 1),j - 1])
初始化&#xff1a;F[i,0] &#61; nArr[i];
*/#include
{//初始化for(int i &#61; 0 ; i
}int RMQ(int a[], int len, int Start, int End)
{//中间变量的选取log2(len)int nlog &#61; (int)(log(double(End-Start&#43;1))/log(2.0));return min(F[Start][nlog], F[End - (1 <
}int main()
{int a[] &#61; {2,34,2,3,23,2,23,1,23,123,23,232,3,25,565,76};for(int i &#61; 0 ; i <16 ; i&#43;&#43;){cout <" ";}cout << endl;SparseTable(a,16);int l, r;while(cin >> l >> r){cout <
}
ST模板
#include
void ST(int a[],int len)
{for(int i &#61; 0 ; i
}int RMQ(int a[],int len, int l, int r)
{int nlog &#61; floor(log(double(r-l&#43;1))/log(2.0));return max((F[l][nlog]),F[r-(1<
}int main()
{int a[10000];int n;cin >> n;for(int i &#61; 0 ; i
}