st表
ST表类似树状数组,线段树这两种算法,是一种用于解决RMQ(Range Minimum/Maximum Query,即区间最值查询)问题的离线算法。
st表的预处理时间复杂度为(O(logn)),查询为(O(1)),而线段树的查询为(O(logn))。
我们定义:(dp[i][j])为 i 到 (i+2^j-1)这个区间内的最值(这里和下面假设是最大值),所以状态转移方程为:
(dp[i][j]=max(dp[i][j-1],dp[i+1<<(j-1)][j-1]))
其代码也很好理解:
void init_rmq()
{
for (int i=1;i<=n;++i)
dp[i][0]=arr[i];
for (int j=1;(1<<j)<=n;++j) //先循环区间,原理同区间dp
for (int i=1;i+(1<<j)-1<=n;++i)
dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
//注意优先级大小,一定要打括号
}
int query(int l,int r)
{
int k=log2(r-l+1); //log2不能写作log...
return max(dp[l][k],dp[r-(1<<k)+1][k]);
}
AC代码:求每m个区间中的最小值(RQM版)
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int arr[maxn],dp[maxn][20];
int n,m;
void init()
{
for(int i=1;i<=n;++i)
dp[i][0]=arr[i];
for(int j=1;(1<<j)<=n;++j)
for(int i=1;i+(1<<j)-1<=n;++i)
dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
int query(int l,int r)
{
int k=log2(r-l+1);
return min(dp[l][k],dp[r-(1<<k)+1][k]);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&arr[i]);
init();
for(int i=1;i<=n-m+1;++i)
printf("%d
",query(i,i+m-1));
system("pause");
}