「题解」P5906 【模板】回滚莫队&不删除莫队
题目
思路
回滚莫队。
考虑普通的莫队,添加一个数可以 \(O(1)\) 更新答案,只需要记录第一次出现的位置就可以。删除一个数想不到什么好的维护方式。就考虑回滚莫队。
记录第一次出现的位置,正常拓展右区间,拓展左区间的时候注意对于左区间来说第一次出现的位置是右区间的最后一次出现的位置。
Code
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define MAXN 200001
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }
int n, m, a[MAXN], b[MAXN], first_[MAXN], ans[MAXN];
int sqrn, num[MAXN], first[MAXN], last[MAXN];
struct lsh {
int w, id;
friend bool operator < (lsh l1, lsh l2) {
return l1.w < l2.w;
}
}l[MAXN];
struct query {
int x, y, id;
friend bool operator < (query q1, query q2) {
if (num[q1.x] != num[q2.x]) return num[q1.x] < num[q2.x];
return q1.y < q2.y;
}
}q[MAXN];
int main() {
scanf("%d", &n), sqrn = sqrt(n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
num[i] = (i - 1) / sqrn + 1;
l[i].w = a[i], l[i].id = i;
}
std::sort(l + 1, l + n + 1);
for (int i = 1, now = 0; i <= n; ++i) {
if (l[i].w != l[i - 1].w) ++now;
b[l[i].id] = now;
}
scanf("%d", &m);
for (int i = 1; i <= m; ++i) {
scanf("%d %d", &q[i].x, &q[i].y);
q[i].id = i;
}
std::sort(q + 1, q + m + 1);
int l = 0, r = 0, lastblock = 0, maxx = 0;
for (int i = 1; i <= m; ++i) {
if (num[q[i].x] == num[q[i].y]) {
int temp = 0;
for (int j = q[i].x; j <= q[i].y; ++j) {
if (first_[b[j]] == 0) first_[b[j]] = j;
else temp = max(temp, j - first_[b[j]]);
}
for (int j = q[i].x; j <= q[i].y; ++j) first_[b[j]] = 0;
ans[q[i].id] = temp; continue;
}
if (num[q[i].x] != lastblock) {
memset(first, 0, sizeof first);
memset(last, 0, sizeof last);
int stop = min(n, num[q[i].x] * sqrn);
l = stop + 1, r = stop, maxx = 0;
lastblock = num[q[i].x];
}
while(r < q[i].y) {
++r;
if (first[b[r]] == 0) first[b[r]] = last[b[r]] = r;
else {
maxx = max(maxx, r - first[b[r]]);
last[b[r]] = r;
}
}
int l_ = l, temp = maxx;
while(l_ > q[i].x) {
--l_;
if (first[b[l_]] == 0 && last[b[l_]] == 0) last[b[l_]] = l_;
else temp = max(temp, last[b[l_]] - l_);
}
while(l_ < l) {
if (last[b[l_]] < first[b[l_]]) last[b[l_]] = first[b[l_]];
++l_;
}
ans[q[i].id] = temp;
}
for (int i = 1; i <= m; ++i) printf("%d\n", ans[i]);
return 0;
}