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;
}
posted @ 2020-01-11 21:23  _Isaunoya  阅读(145)  评论(0)    收藏  举报