前言
介绍
S T ST ST表基于倍增的思想,可以做到 O n l o g n Onlogn Onlogn的预处理, O ( 1 ) O(1) O(1)的查询,不支持修改
思路
对于这种很常见的 R M Q RMQ RMQ问题,我们一般会如下操作 :
状态表示:
f [ i ] [ j ] f[i][j] f[i][j] 表从以 i i i为端点,向右跳 2 j − 1 2^j-1 2j−1的区间中的最大值
状态转移 :
f
[
i
]
[
j
]
=
a
[
i
]
(
j
=
=
0
)
f[i][j]=a[i] (j==0)
f[i][j]=a[i](j==0)
f
[
i
]
[
j
]
=
m
a
x
(
f
[
i
]
[
j
−
1
]
,
f
[
i
+
(
1
<
<
j
−
1
)
]
[
j
−
1
]
)
f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1])
f[i][j]=max(f[i][j−1],f[i+(1<<j−1)][j−1])
为什么这么转移呢 ? 请看下图
[来自oi wiki]
查询操作 :
对于每个询问的 [ L , R ] [L,R] [L,R],我们把它分成两部分, f [ l , l + 2 s − 1 ] 和 f [ r − 2 s + 1 , r ] f[l,l+2^s-1]和f[r-2^s+1,r] f[l,l+2s−1]和f[r−2s+1,r]
其中 s = l o g 2 ( r − l + 1 ) s=log_2(r-l+1) s=log2(r−l+1)
取两个区间的最大值即可
Mycode
const int N = 2e5+10 , M = 30;
int a[N];
int n,m;
int f[N][M];
void init(){
for(int j = 0; j < M ;j ++) {
for(int i=1;i+(1<<j)-1 <= n;i ++ ){
if(!j)f[i][j] = a[i];
else f[i][j] = max(f[i][j-1],f[i+(1<<j-1)][j-1]);
}
}
}
void solve(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
init();
cin>>m;
while(m -- ){
int l,r;cin>>l>>r;
int len = r -l + 1;
int k = log(len)/log(2);
cout<<max(f[l][k],f[r-(1<<k)+1][k])<<endl;
}
}