• ST表学习笔记


    ST表是一种利用DP思想求解最值的倍增算法

    ST表常用于解决RMQ问题,即求解区间最值问题

    接下来以求最大值为例分步讲解一下ST表的建立过程:

    1.定义

    f[i][j]表示[i,i+2j-1]这个长度为2j的区间中的最大值

    2.预处理

    f[i][0]=a[i],即区间[i,i]的最大值就是a[i]

    3.状态转移

    将[i,i+2j-1]平均分成两份,分别为[i,i+2j-1-1]和[i+2j-1,i+2j-1],两段的长度均为2j

    [i,i+2j-1]的最大值为这两段的最大值中的较大值,即f[i][j]=max(f[i][j-1],f[i+2j-1][j-1])

    4.核心代码

    void ST(int n){
        for(int j=1;j<=20;j++)
    //注意要把j放外层,这样可以确保此时f[i+(1<<(j-1))][j-1]已经被赋值了
            for(int i=1;i<=n;i++)//枚举区间左端点
                if(i+(1<<j)-1<=n)
                    f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
    }

    好啦建立好了ST表,接下来我们就可以直接O(1)地查询啦!QWQ

    讲一讲查询的步骤:

    1.查询过程

    若需要查询的区间为[i,j],那么我们需要找到两个覆盖这个闭区间的最小幂区间,这两个区间可以重叠,因为这对区间最大值并没有什么影响。

    这个区间的长度为j-i+1,所以我们要记录一个值k=log2(j-i+1)

    于是就可以得到答案MAX(i,j)=max(f[i][k],f[j-(1<<k)+1][k])

    2.完整代码

     1 #include<bits/stdc++.h>
     2 #define go(i,a,b) for(register int i=a;i<=b;i++)
     3 using namespace std;
     4 const int MAXN=1e6+5;
     5 int a[MAXN],f[MAXN][20];
     6 void ST(int n){
     7     go(j,1,20)
     8         go(i,1,n)
     9         if(i+(1<<j)-1<=n)
    10             f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
    11     return;
    12 }
    13 int main(){
    14     int n,m;
    15     scanf("%d%d",&n,&m);
    16     go(i,1,n) scanf("%d",&a[i]),f[i][0]=a[i];
    17     ST(n);
    18     while(m--){
    19         int i,j;
    20         scanf("%d%d",&i,&j);
    21         int k=(int)(log(j-i+1)/log(2.0));
    22         printf("%d
    ",max(f[i][k],f[j-(1<<k)+1][k]));//O(1)直接查询
    23     }
    24     return 0;
    25 }

    Update!

    加一道例题——

    邻值查找

  • 相关阅读:
    Spring 泛型依赖注入
    Spring 注解配置(2)——@Autowired
    Spring bean注解配置(1)
    Spring bean三种创建方式
    Spring中bean的生命周期!
    spring spel表达式语言
    [转]SVN版本冲突解决详解
    [转]Mybatis极其(最)简(好)单(用)的一个分页插件
    [转]Hibernate查询对象所有字段,单个字段 ,几个字段取值的问题
    [转] JPQL
  • 原文地址:https://www.cnblogs.com/THWZF/p/10380936.html
Copyright © 2020-2023  润新知