ST表

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\n",query(i,i+m-1));
	system("pause");
}
posted @ 2020-02-02 22:00  StungYep  阅读(146)  评论(0编辑  收藏  举报