📅  最后修改于: 2023-12-03 14:57:12.012000             🧑  作者: Mango
在计算机科学中,范围最小查询是一个常见的问题,用于在数列中找到一段区间内的最小元素。平方根分解和稀疏表是两种常见且高效的解决方法。
平方根分解的思想是将原数据分块,每个块的大小为 $\sqrt{n}$,其中 $n$ 是数列的大小。对于每个块,我们可以预处理出该块内的最小元素,并将这些值存储在一个辅助数组中。
查询时,我们可以确定查询区间内的每个块,然后在辅助数组中所在块的最小元素中找到最小值。接着,我们可以遍历相应的块,以查找该块中的最小元素,并返回区间内所有块中的最小元素。
平方根分解的时间复杂度为 $O(\sqrt{n})$,空间复杂度也为 $O(\sqrt{n})$。
以下是平方根分解的 Python 代码实现:
import math
class SquareRootDecomposition:
def __init__(self, arr):
block_size = math.isqrt(len(arr))
self.blocks = [float("inf")] * (len(arr) // block_size + 1)
self.min_in_block = [float("inf")] * len(arr)
for i in range(len(arr)):
self.min_in_block[i] = arr[i]
if self.blocks[i // block_size] > arr[i]:
self.blocks[i // block_size] = arr[i]
def query(self, l, r):
block_size = int(math.isqrt(len(self.min_in_block)))
left_block = l // block_size
right_block = r // block_size
ans = float("inf")
for i in range(l, min((left_block + 1) * block_size, r + 1)):
ans = min(ans, self.min_in_block[i])
for i in range(left_block + 1, right_block):
ans = min(ans, self.blocks[i])
for i in range(right_block * block_size, r + 1):
ans = min(ans, self.min_in_block[i])
return ans
稀疏表的思想是将原数据拆分成一系列累加和数组,并将这些数组保存在一个二维表格中。每个格子 $(i, j)$ 中存储的是从位置 $i$ 开始,长度为 $2^j$ 的子段的最小值。
我们可以通过对表格预处理来回答查询。对于任何子段 $[l, r]$,我们可以在 $O(1)$ 时间内找到两个相邻的长度为 $2^j$ 的子段,其中 $l$ 在第一个子段中,$r$ 在第二个子段中。查询的答案即是这两个子段的最小值。
稀疏表的时间复杂度为 $O(n \log{n})$,空间复杂度为 $O(n \log{n})$。
以下是稀疏表的 Python 代码实现:
class SparseTable:
def __init__(self, arr):
n = len(arr)
log_n = int(math.ceil(math.log2(n)))
self.st = [[float("inf")] * (log_n + 1) for _ in range(n)]
for i in range(n):
self.st[i][0] = arr[i]
for j in range(1, log_n + 1):
for i in range(n):
if i + (1 << j) > n:
break
self.st[i][j] = min(self.st[i][j - 1], self.st[i + (1 << (j - 1))][j - 1])
def query(self, l, r):
j = int(math.floor(math.log2(r - l + 1)))
return min(self.st[l][j], self.st[r - (1 << j) + 1][j])
总的来说,平方根分解和稀疏表都是高效解决范围最小查询的方法。我们可以根据具体问题的复杂度和性能要求选择合适的算法。