码迷,mamicode.com
首页 > 其他好文 > 详细

ST表

时间:2018-10-06 00:56:53      阅读:512      评论:0      收藏:0      [点我收藏+]

标签:cpp   print   cst   cin   define   复杂度   中间   支持   log   

ST表

ST表是什么?

  • ST表就是一个用来解决区间最值的算法
  • 它不支持动态修改
  • 预处理时间复杂度O(nlogn),查询复杂度O(1)

ST表的原理?

  • 利用了倍增的思想,建表即把给定区间分成长度是2的幂次的小区间,然后从小区间递推到大区间。查询在后面会讲解

ST表的主要变量?

  • f[i][j]:表示区间[i,i+pow(2,j)-1]中的最值
  • a[i]:存储原有序列
  • logMax:作为f[i][j]中j的循环上界(含义跟LCA里的logMaxn类似)

建表

  • 建表的核心变量就是,通过小区间转移到大区间的原理得出整个区间的最值
  • 如何转移?
    • f[i][j]=max(f[i][j-1],f[i+pow(2,j-1)][j-1]);
    • 即把[i, i+pow(2, j)-1]区间分为[i, i+pow(2, j-1)-1]和[i+pow(2, j-1), i+pow(2, j-1)+pow(2, j-1)]两个区间。原理也跟LCA中的f数组转移类似

查询

  • 首先明白一个定理:
    2^log2(n)>n/2
    这个很简单,因为log2(n)表示小于等于n的2的最大几次方。
    那么我们要查询x到y的最小值。
    设len=y-x+1,p=log2(len)
    根据上面的定理:2^p>len/2
    从位置上来说,x+2^p越过了x到y的中间!
    因为位置过了一半
    所以x到y的最小值可以表示为min(从x往后2^p^的最小值, 从y往前2^p^的最小值)
    前面的状态表示为f[x][p]
    设后面(从y往前2^p^的最小值)的初始位置是k,
    那么k+2^p^-1=y,所以k=y-2^p^+1
    所以后面的状态表示为f[y-2^p^+1][p]
    所以x到y的最小值表示为min(f[x]p], f[y-2^p^+1][p])

代码实现

以模版题为例:传送门

#include <iostream>
#include <cstdio>
#include <cmath>
#define maxn 100005
using namespace std;

int n, q, logMax;
int a[maxn];
int f[maxn][31];

int read()
{
    int x=0, f=1; char c=getchar();
    while(c<'0' || c>'9') {if(c=='-') f=-1; c=getchar();}
    while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();}
    return x*=f;
}

int main()
{
    cin>>n>>q;
    logMax=(int)log2(n);
    for(int i=1;i<=n;i++) a[i]=read(), f[i][0]=a[i];
    for(int j=1;j<=logMax;j++)
        for(int i=1;i<=n-(1<<j)+1;i++)  //1<<i 等价于 pow(2, i)
            f[i][j]=max(f[i][j-1], f[i+(1<<(j-1))][j-1]);
    for(int i=1;i<=q;i++)
    {
        int l=read(), r=read();
        int p=(int)log2(r-l+1);
        printf("%d\n",max(f[l][p], f[r-(1<<p)+1][p]));
    }
    return 0;
}

ST表

标签:cpp   print   cst   cin   define   复杂度   中间   支持   log   

原文地址:https://www.cnblogs.com/BigYellowDog/p/9746426.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!