为了解决该问题,有一个算法叫 the Method of Four Russians,其时间复杂度为0(n + m),步骤如下:X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
• 建立 Cartesian(笛卡尔)树,将问题转化为树上的 LCA(最近公共祖先)问题。X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
• 对于 LCA 问题,可以考虑其 Euler 序(即按照 DFS 过程,经过所有点,环游回根的序列),即求 Euler 序列上两点间一个新的 RMQ 问题。X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
• 注意新的问题为 ±1 RMQ,即相邻两点的深度差一定为 1。X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
下面解决这个 ±1 RMQ 问题,“序列”指 Euler 序列:X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
• 设 t 为 Euler 序列长度。取 b =将序列每 b 个分为一大块, 使用 ST 表(倍增表)处理大块间的 RMQ 问题,复杂度X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
• (重点)对于一个块内的 RMQ 问题,也需要O(1) 的算法。由于差分数组 2b-1X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
种,可以预处理出所有情况下的最值位置,预处理复杂度 O(b2b),不超过 O(n)。X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
• 最终,对于一个查询,可以转化为中间整的大块的 RMQ 问题,以及两端块内的 RMQ 问题。X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
试补全程序。X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
#include <iostream>X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
#include <cmath>X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
using namespace std;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
const int MAXN = 100000, MAXT = MAXN << 1;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
const int MAXL = 18, MAXB = 9, MAXC = MAXT / MAXB;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
struct node {X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
int val;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
int dep, dfn, end;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
node *son[2]; // son[0], son[1] 分别表示左右儿子X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
} T[MAXN];X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
int n, t, b, c, Log2[MAXC + 1];X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
int Pos[(1 << (MAXB - 1)) + 5], Dif[MAXC + 1];X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
node *root, *A[MAXT], *Min[MAXL][MAXC];X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
void build() { // 建立 Cartesian 树X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
static node *S[MAXN + 1];X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
int top = 0;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
for (int i = 0; i < n; i++) {X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
node *p = &T[i];X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
while (top && S[top]->val < p->val)X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
①;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
if (top)X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
②;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
S[++top] = p;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
}X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
root = S[1];X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
}X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
void DFS(node *p) { // 构建 Euler 序列X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
A[p->dfn = t++] = p;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
for (int i = 0; i < 2; i++)X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
if (p->son[i]) {X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
p->son[i]->dep = p->dep + 1;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
DFS(p->son[i]);X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
A[t++] = p;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
}X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
p->end = t - 1;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
}X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
node *min(node *x, node *y) {X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
return ③ ? x : y;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
}X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
void ST_init() {X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
b = (int)(ceil(log2(t) / 2));X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
c = t / b;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
Log2[1] = 0;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
for (int i = 2; i <= c; i++)X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
Log2[i] = Log2[i >> 1] + 1;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
for (int i = 0; i < c; i++) {X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
Min[0][i] = A[i * b];X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
for (int j = 1; j < b; j++)X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
Min[0][i] = min(Min[0][i], A[i * b + j]);X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
}X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
for (int i = 1, l = 2; l <= c; i++, l <<= 1)X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
for (int j = 0; j + l <= c; j++)X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
Min[i][j] = min(Min[i - 1][j], Min[i - 1][j + (l >> 1)]);X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
}X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
void small_init() { // 块内预处理X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
for (int i = 0; i <= c; i++)X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
for (int j = 1; j < b && i * b + j < t; j++)X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
if (④)X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
Dif[i] |= 1 << (j - 1);X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
for (int S = 0; S < (1 << (b - 1)); S++) {X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
int mx = 0, v = 0;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
for (int i = 1; i < b; i++) {X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
⑤;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
if (v < mx) {X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
mx = v;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
Pos[S] = i;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
}X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
}X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
}X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
}X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
node *ST_query(int l, int r) {X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
int g = Log2[r - l + 1];X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
return min(Min[g][l], Min[g][r - (1 << g) + 1]);X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
}X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
node *small_query(int l, int r) { // 块内查询X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
int p = l / b;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
int S = ⑥;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
return A[l + Pos[S]];X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
}X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
node *query(int l, int r) {X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
if (l > r)X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
return query(r, l);X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
int pl = l / b, pr = r / b;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
if (pl == pr) {X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
return small_query(l, r);X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
} else {X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
node *s = min(small_query(l, pl * b + b - 1), X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
small_query(pr * b, r));X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
if (pl + 1 <= pr - 1)X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
s = min(s, ST_query(pl + 1, pr - 1));X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
return s;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
}X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
}X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
int main() {X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
int m;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
cin >> n >> m;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
for (int i = 0; i < n; i++)X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
cin >> T[i].val;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
build();X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
DFS(root);X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
ST_init();X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
small_init();X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
while (m--) {X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
int l, r;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
cin >> l >> r;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
cout << query(T[l].dfn, T[r].dfn)->val << endl;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
}X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
return 0;X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库
}X87100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库