4358: permu
4358: permu
分析:
不删除的莫队+可撤销的并查集。
每次询问先固定左端点到一个块内,然后将这些右端点从小到大排序,然后询问的过程中,右端点不断往右走,左端点可能会撤销,但是移动区间不超过$\sqrt n$个,用带撤销的并查集维护。
复杂度$O(n \sqrt n log n)$
代码:
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #include<cmath> #include<cctype> #include<set> #include<queue> #include<vector> #include<map> #include<bitset> using namespace std; typedef long long LL; inline int read() { int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; } const int N = 50005; int bel[N], a[N], ans[N], fa[N], dep[N], B, Top, Mx, n; bool vis[N]; struct Que{ int l, r, id; } ; struct Node{ int x, d; } sk[N << 1]; // N * 2 !!! bool operator < (const Que &A,const Que &B) { return A.r < B.r; } vector< Que > q[N]; int solve1(int x,int y) { if (x == y) return 1; vector<int>vec; for (int i = x; i <= y; ++i) vec.push_back(a[i]); sort(vec.begin(), vec.end()); int res = 1, now = 1; for (int i = 1; i < (int)vec.size(); ++i) vec[i] == vec[i - 1] + 1 ? now ++ : now = 1, res = max(res, now); // !!! return res; } int find(int x) { return x == fa[x] ? x : find(fa[x]); } void Union(int x,int y) { x = find(x), y = find(y); if (x == y) return ; if (dep[x] < dep[y]) swap(x, y); Mx = max(Mx, dep[x] + dep[y]); fa[y] = x; sk[++Top] = (Node){x, dep[x]}; sk[++Top] = (Node){y, dep[y]}; dep[x] += dep[y]; } void add(int x) { vis[x] = 1; if (vis[x - 1]) Union(x - 1, x); if (vis[x + 1]) Union(x, x + 1); } void solve(int now,vector<Que> &vec) { Top = 0, Mx = 1; int pos = min(N, now * B) + 1, lastpos, lastmx, L = pos, R = pos - 1; for (int i = 0; i <= n; ++i) fa[i] = i, dep[i] = 1, vis[i] = 0; for (int i = 0; i < (int)vec.size(); ++i) { Que v = vec[i]; while (R < v.r) add(a[++R]); lastmx = Mx, lastpos = Top; while (L > v.l) add(a[--L]); ans[v.id] = Mx; Mx= lastmx; while (Top > lastpos) fa[sk[Top].x] = sk[Top].x, dep[sk[Top].x] = sk[Top].d, Top --; while (L < pos) vis[a[L ++]] = 0; } } int main() { n = read();int m = read(); B = sqrt(n); for (int i = 1; i <= n; ++i) a[i] = read(), bel[i] = (i - 1) / B + 1; for (int i = 1; i <= m; ++i) { int x = read(), y = read(); if (bel[x] == bel[y]) ans[i] = solve1(x, y); else q[bel[x]].push_back((Que){x, y, i}); } for (int i = 1; i <= bel[n]; ++i) sort(q[i].begin(), q[i].end()), solve(i, q[i]); for (int i = 1; i <= m; ++i) printf("%d\n", ans[i]); return 0; }