(RMQ 区间最值问题)给定序列 (𝑎)0 ,…,(𝑎)n-1,和 𝑚 次询问,每次询问给定 𝑙,𝑟,求 max{(𝑎)𝑙,…,(𝑎)𝑟} 。 为了解决该问题,有一个算法叫 the Method of Four Russians,其时间复杂度为 O(𝒏+𝒎),步骤如下: • 建立 Cartesian(笛卡尔)树,将问题转化为树上的 LCA(最近公共祖先)问题。 • 对于 LCA 问题,可以考虑其 Euler 序(即按照 DFS 过程,经过所有点,环游回根的序列),即求 Euler 序列上两点间一个新的 RMQ 问题。 • 注意新的问题为 ±1 RMQ,即相邻两点的深度差一定为 1。
下面解决这个 ±1 RMQ 问题,“序列”指 Euler 序列: • 设 𝑡 为 Euler 序列长度。取 𝑏=[(log)2 t/2]将序列每 𝑏 个分为一大块, 使用 ST 表(倍增表)处理大块间的 RMQ 问题,复杂度 𝑂(t/b logt) =𝑂(𝑛)。 • (重点)对于一个块内的 RMQ 问题,也需要𝑂(1) 的算法。由于差分数组 2 种,可以预处理出所有情况下的最值位置,预处理复杂度 𝑂((b2)b) ),不超过 𝑂(𝑛)。 • 最终,对于一个查询,可以转化为中间整的大块的 RMQ 问题,以及两端块内的 RMQ 问题。
补全程序。
cpp
1#include <iostream>
2#include <cmath>
3using namespace std;
4,[object Object],
5,[object Object],
6,[object Object],
7,[object Object],
8,[object Object],
9,[object Object],
10,[object Object],
11,[object Object],
12,[object Object],
13,[object Object],
14,[object Object],
cpp
1int main() {,[object Object],
2int m;,[object Object],
3cin >> n >> m;,[object Object],
4for (int i = 0; i < n; i++),[object Object],
5cin >> T[i].val;,[object Object],
6build();,[object Object],
7DFS(root);,[object Object],
8ST_init();,[object Object],
9small_init();,[object Object],
10while (m--) {,[object Object],
11int l, r;,[object Object],
12cin >> l >> r;,[object Object],
13cout << query(T[l].dfn, T[r].dfn)->val << endl;,[object Object],
14},[object Object],
15return 0;,[object Object],
16},[object Object],