代码对着题解看的,现在只理解了一部分。。。
对于有 //qwqqwq.. 的那一行,我看题解说的是不跳到最后,那么题解为什么 20∼0 枚举啊?
顺便求求给代码解释一下,谢谢。
#include <cstring>
#include <iostream>
const int N = 1e5 + 10;
int T, n, a[N], q;
int nxt[N][30], pos[15];
// nxt[i][j]:后面的第 2^j 个与 a[i] 相等的值的位置
// pos[i]:当前最前面的一个 i 的位置
int main() {
std::cin.tie(0)->sync_with_stdio(0);
for (std::cin >> T; T; --T) {
std::cin >> n;
memset(pos, 0, sizeof(pos)); // 多测清空
for (int i = 1; i <= n; ++i) {
std::cin >> a[i];
for (int j = 0; j <= 20; ++j) // 全部初始化
nxt[i][j] = n + 1; // 初始化为一个极大值
}
for (int i = n; i; --i) {
if (pos[a[i]] == 0) { // 不存在下一个 a[i]
nxt[i][0] = n + 1; // 下一个即为一个极大值
pos[a[i]] = i; // pos[a[i]] 是当前的位置
} else { // 存在下一个 a[i]
nxt[i][0] = pos[a[i]]; // 下一个
pos[a[i]] = i; // pos[a[i]] 是当前的位置
}
}
for (int i = n; i; --i) { // 第 i 个位置
for (int j = 1; j <= 20; ++j) // 向后 2^j 步
if (nxt[i][j - 1] + 1 <= n) { // 当前位置下一个相同值不是最后一个数
nxt[i][j] = nxt[nxt[i][j - 1] + 1][j - 1]; //
}
}
std::cin >> q;
for (int l, r, i, ans; q; --q) {
std::cin >> l >> r, i = l, ans = 0;
while (i <= r) {
while (i <= r && nxt[i][0] > r) ++i, ++ans; // [l,r] 内部存在下一个相同值,持续向后移动
if (i > r) break; // 出界
for (int j = 0; j <= 20; ++j) // qwqqwq
if (nxt[i][j] <= r) {
i = nxt[i][j];
break;
}
++i;
}
std::cout << ans << '\n';
}
}
std::cout.flush();
return 0;
}