CF1707E 题解
题目链接
题意描述:给定长度为
定义
定义
定义
定义
即
而
即
所以如果
发现它像区间最值一样可以合并。于是设
还有最后一件事,答案的上界是
#include <bits/stdc++.h>
using namespace std;
namespace QYB {
int n, q, a[100005], log2[100005], minn[18][100005], maxn[18][100005];
pair<int, int> g[18][18][100005];
pair<int, int> extend(pair<int, int> s, int k) {
// 利用 g 数组将 s 拓展 2 ^ k 次
int l = s.first, r = s.second, t = log2[r - l + 1];
pair<int, int> s1 = g[k][t][l], s2 = g[k][t][r - (1 << t) + 1];
return make_pair(min(s1.first, s2.first), max(s1.second, s2.second));
} int main() {
scanf("%d%d", &n, &q); log2[0] = -1;
for (int i = 1; i <= n; i++) {
scanf("%d", a + i); log2[i] = log2[i / 2] + 1;
minn[0][i] = maxn[0][i] = a[i];
} for (int i = 1; i <= 17; i++) {
for (int j = 1; j + (1 << i) - 1 <= n; j++) {
maxn[i][j] = max(maxn[i - 1][j], maxn[i - 1][j + (1 << i - 1)]);
minn[i][j] = min(minn[i - 1][j], minn[i - 1][j + (1 << i - 1)]);
}
} for (int i = 1; i <= 17; i++) {
for (int j = 1; j + (1 << i) - 1 <= n; j++) {
g[0][i][j] = make_pair(minn[i][j], maxn[i][j]);
}
} for (int i = 1; i <= 17; i++) {
for (int j = 1; j <= 17; j++) {
for (int k = 1; k + (1 << j) - 1 <= n; k++) {
// 由于这个时候 g[i - 1][][] 已经计算完毕了,所以这时调用 extend 是可以的
g[i][j][k] = extend(extend(make_pair(k, k + (1 << j) - 1), i - 1), i - 1);
}
}
} while (q--) {
int l, r, ans = 0; scanf("%d%d", &l, &r);
if (l == 1 && r == n) { printf("0\n"); continue; }
// 特判一手,因为下面至少会拓展 1 次
for (int i = 17; i >= 0; i--) {
auto tmp = extend(make_pair(l, r), i);
if (tmp != make_pair(1, n)) {
ans |= 1 << i; l = tmp.first; r = tmp.second;
}
} if (ans == (1 << 18) - 1) printf("-1\n");
else printf("%d\n", ans + 1);
} return 0;
}
} int main() {
return QYB::main();
}