数组不改、反复查区间最大值:先预处理所有“2 的幂长度”的块,查询时用两个会重叠的大块拼出区间,O(1) 出答案。
求 max 可以重叠,所以任意区间 [l,r] 都能被两个长度 2^k 的块盖住:
一个贴左端、一个贴右端,取两块最大值即可。
本题没有修改、查询多达 2×10⁶ 次。ST 表查询严格 O(1),
比线段树 O(log n) 更稳,是静态区间最值的天花板。
预处理:st[i][j] = 从 i 起、长 2ʲ 的区间最大值。
一个长 2ʲ 的块 = 左右两个长 2ʲ⁻¹ 的块:st[i][j]=max(st[i][j-1], st[i+2^(j-1)][j-1])。
查询 [l,r]:令 k=⌊log2(r-l+1)⌋,
答案 = max(st[l][k], st[r-2^k+1][k])。两块都长 2^k,必定盖满且可重叠。
数组(下标 1~8):9 3 1 7 5 6 0 8。查询区间 [2,7],长度 6。
Q1. ST 表能用“两块重叠”查询,靠的是什么性质?
Q2. 查询 [2,7](长 6),应取 k = ?
Q3. 下面哪种问法 不能直接用这套“两块重叠”?
| 步骤 | 取值 | 结果 |
|---|---|---|
| 区间长度 | r-l+1 = 7-2+1 = 6 | k=⌊log2 6⌋=2,2ᵏ=4 |
| 左块 [l, l+2ᵏ-1] | [2,5] = {3,1,7,5} | max = 7 |
| 右块 [r-2ᵏ+1, r] | [4,7] = {7,5,6,0} | max = 7 |
| max(7, 7) | 答案 = 7 | |
r-2^k+1(贴右端),别写成 l+2^k。lg[] 预处理出每个长度的 log2,查询时直接查表更快。