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
", ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/mjtcn/p/10630605.html