P5906 【模板】回滚莫队
我菜的可怜,回滚莫队这玩意还会WA很多次。
定义 \(q_i\) 是询问
回滚莫队的做法大概就是:
按左端点所在的块排序 如果相同 按右端点排序
然后对于每个块求解。弄个右指针在块的最右边。
分类讨论一下 如果左右指针共处一个块内 直接暴力 就是根号级别的
如果不在一个块内 由于右端点是递增的 考虑移动右端点
左边的贡献直接从 \(q[i].l\) ~ 块的最右边 暴力就行了
由于不能删除,每次记录之前的状态,然后复制一遍,再操作,最后回归状态,没了。
易证复杂度:
对于整块的询问 一共有 \(\sqrt n\) 个块 右端点每次都是当前块的右端点 所以最多移动 \(n\)的长度
对于每个询问 考虑左边的端点 由于按左端点排序 左端点和右端点最多相差 \(\sqrt n\) 的长度
这样就可以做到 \(O(n\sqrt n + q\sqrt n)\) 了
对于每个块随便搞就可以了。
还有,40pts的能不能加强数据啊(
\(\texttt{code}\):
// by Isaunoya
#include <bits/stdc++.h>
using namespace std;
#define rep(i, x, y) for (register int i = (x); i <= (y); ++i)
#define Rep(i, x, y) for (register int i = (x); i >= (y); --i)
const int _ = 1 << 21;
struct I {
char fin[_], *p1 = fin, *p2 = fin;
inline char gc() {
return (p1 == p2) && (p2 = (p1 = fin) + fread(fin, 1, _, stdin), p1 == p2) ? EOF : *p1++;
}
inline I& operator>>(int& x) {
bool sign = 1;
char c = 0;
while (c < 48) ((c = gc()) == 45) && (sign = 0);
x = (c & 15);
while ((c = gc()) > 47) x = (x << 1) + (x << 3) + (c & 15);
x = sign ? x : -x;
return *this;
}
inline I& operator>>(double& x) {
bool sign = 1;
char c = 0;
while (c < 48) ((c = gc()) == 45) && (sign = 0);
x = (c - 48);
while ((c = gc()) > 47) x = x * 10 + (c - 48);
if (c == '.') {
double d = 1.0;
while ((c = gc()) > 47) d = d * 0.1, x = x + (d * (c - 48));
}
x = sign ? x : -x;
return *this;
}
inline I& operator>>(char& x) {
do
x = gc();
while (isspace(x));
return *this;
}
inline I& operator>>(string& s) {
s = "";
char c = gc();
while (isspace(c)) c = gc();
while (!isspace(c) && c != EOF) s += c, c = gc();
return *this;
}
} in;
struct O {
char st[100], fout[_];
signed stk = 0, top = 0;
inline void flush() { fwrite(fout, 1, top, stdout), fflush(stdout), top = 0; }
inline O& operator<<(int x) {
if (top > (1 << 20)) flush();
if (x < 0) fout[top++] = 45, x = -x;
do
st[++stk] = x % 10 ^ 48, x /= 10;
while (x);
while (stk) fout[top++] = st[stk--];
return *this;
}
inline O& operator<<(char x) {
fout[top++] = x;
return *this;
}
inline O& operator<<(string s) {
if (top > (1 << 20)) flush();
for (char x : s) fout[top++] = x;
return *this;
}
} out;
#define pb emplace_back
#define fir first
#define sec second
template <class T>
inline void cmax(T& x, const T& y) {
(x < y) && (x = y);
}
template <class T>
inline void cmin(T& x, const T& y) {
(x > y) && (x = y);
}
const int maxn = 2e5 + 10;
int S, n, m;
struct Que {
int l, r, id;
} q[maxn];
int a[maxn], b[maxn], bl[maxn], Ans[maxn], fir[maxn], las[maxn], Fir[maxn], Las[maxn];
inline int calc(int l, int r) {
rep(i, l, r) Fir[a[i]] = 1e9, Las[a[i]] = 0;
int ans = 0;
rep(i, l, r) {
cmin(Fir[a[i]], i), cmax(Las[a[i]], i);
cmax(ans, Las[a[i]] - Fir[a[i]]);
}
return ans;
}
int now = 1, ansl = 0, ansr = 0;
inline void add(const int& x, int& ans) {
cmin(fir[a[x]], x), cmax(las[a[x]], x), cmax(ans, las[a[x]] - fir[a[x]]);
}
inline int max(const int& x, const int& y) { return x > y ? x : y; }
inline void solve(const int& id) {
int qr = id * S;
cmin(qr, n), ansr = 0;
rep(i, (id - 1) * S + 1, n) fir[a[i]] = 1e9, las[a[i]] = 0;
register int pr = qr;
for (; bl[q[now].l] == id; ++now) {
if (bl[q[now].l] == bl[q[now].r]) {
Ans[q[now].id] = calc(q[now].l, q[now].r);
continue;
}
while (pr < q[now].r) add(++pr, ansr);
rep(i, q[now].l, qr) Fir[a[i]] = fir[a[i]], Las[a[i]] = las[a[i]];
ansl = 0;
Rep(i, qr, q[now].l) add(i, ansl);
Ans[q[now].id] = max(ansl, ansr), ansl = 0;
rep(i, q[now].l, qr) fir[a[i]] = Fir[a[i]], las[a[i]] = Las[a[i]];
}
}
signed main() {
#ifdef _WIN64
freopen("testdata.in", "r", stdin);
#endif
in >> n, S = sqrt(n * 0.9);
rep(i, 1, n) in >> a[i];
rep(i, 1, n) b[i] = a[i], bl[i] = (i - 1) / S + 1;
sort(b + 1, b + n + 1, [](const int& x, const int& y) { return x < y; });
int len = unique(b + 1, b + n + 1) - b - 1;
rep(i, 1, n) a[i] = lower_bound(b + 1, b + len + 1, a[i]) - b;
rep(i, 1, n) Fir[i] = fir[i] = 1e9;
in >> m;
rep(i, 1, m) { in >> q[i].l >> q[i].r, q[i].id = i; }
sort(q + 1, q + m + 1, [](const Que& x, const Que& y) {
if (bl[x.l] ^ bl[y.l]) return bl[x.l] < bl[y.l];
return x.r < y.r;
});
rep(i, 1, bl[n]) solve(i);
rep(i, 1, m) out << Ans[i] << '\n';
return out.flush(), 0;
}

浙公网安备 33010602011771号