首先感谢博客:Misaka Mikoto
以及up主:星垂月朦胧
我是看到这篇博客和up主后对ST表的建立和查询有了一定的了解。写这篇博客也是为了做下笔记,方便复习!
一:ST表的建立
dp五部曲:
-
dp[i][j]:表示区间左端点为 i i i,长度为 2 j 2^j 2j的区间最大元素,即: m a x [ i , i + 2 j − 1 ] max[i, i+2^j-1] max[i,i+2j−1]
-
d p [ i ] [ j ] = m a x ( d p [ i ] [ j − 1 ] , d p [ i + 2 j − 1 ] [ j − 1 ] ) dp[i][j]=max(dp[i][j-1], dp[i+2^{j-1}][ j-1]) dp[i][j]=max(dp[i][j−1],dp[i+2j−1][j−1])
-
初始化: d p [ i ] [ 0 ] = a [ i ] ( i ∈ [ 1 , n ] ) dp[i][0]=a[i](i\in[1, n]) dp[i][0]=a[i](i∈[1,n])
-
遍历顺序:容易看出状态转移方程中求 i i i 需要知道后面的状态 2 j − 1 2^{j-1} 2j−1,而求 j j j 需要知道前面的状态 j − 1 j-1 j−1 。所以先遍历j,再遍历i:
f o r j i n [ 1 , l o g 2 n ] for ~~ j~~~ in ~~~[1, log_2 n] for j in [1,log2n]:
f o r i i n [ 1 , n − 2 j + 1 ] ~~~~~~~for~~~i~~~~in~~~~[1, n-2^j+1] for i in [1,n−2j+1] -
手动模拟
二:ST表的查询
~~~~
查询[l, r]区间的最大值?
- l e n = ( r − l + 1 ) len=(r-l+1) len=(r−l+1)
- j = l o g 2 l e n j=log_2 len j=log2len
- a n s = m a x ( d p [ l ] [ j ] , d p [ r − 2 j + 1 ] [ j ] ) ans = max(dp[l][j], dp[r-2^j+1][j]) ans=max(dp[l][j],dp[r−2j+1][j])
三:模板题
P3865 【模板】ST表
四: Python代码的实现:
(可能是Python本身慢的问题,没有AC;C++可以AC,但是如果用cin cout仍然是AC不了的!)
import math
dp = []
a = []
n, m = 0, 0
def ST():
global dp, n, m, a
for i in range(1, n+1):
dp[i][0] = a[i]
for j in range(1, int(math.log(n, 2)+1)):
for i in range(1, n-(1<<j)+1+1): # 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])
return
def query(l, r):
global dp
len = (r-l+1)
j = int(math.log(len, 2))
return max(dp[l][j], dp[r-(1<<j)+1][j])
def main():
global dp, n, m, a
n, m = list(map(int, input().split()))
dp = [[0 for i in range(int(math.log(n, 2))+10)] for i in range(n+1)]
a = [-1] + list(map(int, input().split()))
ST()
for i in range(m):
l, r = list(map(int, input().split()))
print(query(l, r))
return
main()
#include<cmath>
#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
ll n, m;
//ll a[100010];
ll dp[100010][20];
void ST(){
/*for(int i=1; i<=n; i++){
dp[i][0] = a[i];
}*/
for(int j=1; j<=int(log(n)/log(2)); j++){
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]);
}
}
}
ll query(ll l, ll r){
ll len = (r-l+1);
ll j = int(log(len)/log(2));
return max(dp[l][j], dp[r-(1<<j)+1][j]);
}
int main()
{
//cin>>n>>m;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++){
scanf("%d",&dp[i][0]);
//cin>>dp[i][0];
}
int l, r;
ST();
for(int i=1; i<=m; i++){
//cin>>l>>r;
scanf("%d%d",&l,&r);
printf("%d\n",query(l, r));
//cout<<query(l, r)<<endl;
}
/*while(cin>>l>>r){
cout<<query(l, r)<<endl;
}*/
return 0;
}