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\n",max(f[i][k],f[j-(1<<k)+1][k]));//O(1)直接查询
23     }
24     return 0;
25 }

Update!

加一道例题——

邻值查找

posted @ 2019-02-14 21:46  小叽居biubiu  阅读(254)  评论(0编辑  收藏  举报