浅谈ST表

浅谈ST表

先丢个板子:

https://www.luogu.org/problemnew/show/P3865

基本思路:

ST表运用的是 倍增+动态规划 的思想,预处理的时间复杂度是O(nlogn),查询是O(1)的。

ST表的存储是用的二位数组st [ i ] [ j ] ,表示以第I位开头,长度为2^J的区间。

题目:给定一个长度为 N 的数列,和 M 次询问,求出每一次询问的区间内数字的最大(小)值。

这里我们只谈最大值,因为最小值也是同样的道理,把函数Max改成Min就可以了。

 

具体实现:

输入:把长度为N的序列存到ST[ i ] [ 0 ] 中,因为以i开头长度为2^0就是i。

 

预处理:动态规划解决,st[ j ][ i ]=max(st[ j ][ i-1],st[ j+(1<<( i-1 ))] [i-1]);

当前区间最大值由两个子区间最大值得来。

 

输出:从两个重叠的子区间取最大值。

 

代码:

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int n,stb[100005][22],m;//以I开头,长度为2^j的区间
void init()
{
    for(register int i=1;i<=21;i++)
    for(register int j=1;(j+(1<<i)-1)<=n;j++)
    stb[j][i]=max(stb[j][i-1],stb[j+(1<<(i-1))][i-1]);
}
void query(int l,int r)
{
    int k=log2(r-l+1);
    printf("%d\n",max(stb[l][k],stb[r-(1<<k)+1][k]));
}
int main()
{
    scanf("%d%d",&n,&m);
    for(register int i=1;i<=n;i++)
    scanf("%d",&stb[i][0]);
    init();
    for(register int i=1;i<=m;i++)
    {
    int l,r;
    scanf("%d%d",&l,&r);
    query(l,r);
    }
    return 0;
}

 

我比较懒,所以代码里注释极少...

 

posted @ 2018-07-31 16:13  zxza695  阅读(211)  评论(0编辑  收藏  举报

Contact with me