BZOJ4358: permu(带撤销并查集 不删除莫队)
程序员文章站
2022-05-27 22:30:00
题意 "题目链接" Sol 感觉自己已经老的爬不动了。。 想了一会儿,大概用个不删除莫队+带撤销并查集就能搞了吧,$n \sqrt{n} logn$应该卡的过去 不过不删除莫队咋写来着?。。。。跑去学。。 带撤销并查集咋写来着?。。。。跑去学。。。 发现自己的带撤销并查集是错的,,自己yy着调了1h ......
题意
sol
感觉自己已经老的爬不动了。。
想了一会儿,大概用个不删除莫队+带撤销并查集就能搞了吧,\(n \sqrt{n} logn\)应该卡的过去
不过不删除莫队咋写来着?。。。。跑去学。。
带撤销并查集咋写来着?。。。。跑去学。。。
发现自己的带撤销并查集是错的,,自己yy着调了1h终于过了大数据。。
#include<bits/stdc++.h> #define pair pair<int, int> #define mp(x, y) make_pair(x, y) #define fi first #define se second //#define int long long #define ll long long #define fin(x) {freopen(#x".in","r",stdin);} #define fout(x) {freopen(#x".out","w",stdout);} #define pb(x) push_back(x) using namespace std; const int mod = 1e9 + 7; const int maxn = 1e6 + 10; template <typename a, typename b> inline bool chmin(a &a, b b){if(a > b) {a = b; return 1;} return 0;} template <typename a, typename b> inline bool chmax(a &a, b b){if(a < b) {a = b; return 1;} return 0;} template <typename a, typename b> inline ll add(a x, b y) {if(x + y < 0) return x + y + mod; return x + y >= mod ? x + y - mod : x + y;} template <typename a, typename b> inline void add2(a &x, b y) {if(x + y < 0) x = x + y + mod; else x = (x + y >= mod ? x + y - mod : x + y);} template <typename a, typename b> inline ll mul(a x, b y) {return 1ll * x * y % mod;} template <typename a, typename b> inline void mul2(a &x, b y) {x = (1ll * x * y % mod + mod) % mod;} template <typename a> inline void debug(a a){cout << a << '\n';} template <typename a> inline ll sqr(a x){return 1ll * x * x;} inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int n, m, a[maxn], belong[maxn], block, ans[maxn], cnt, fa[maxn]; struct q { int l, r, id; bool operator < (const q &rhs) const{ return r < rhs.r; } }; vector<q> q[maxn]; int solveblock(int x, int y) { if(x == y) return 1; vector<int> v; for(int i = x; i <= y; i++) v.pb(a[i]); sort(v.begin(), v.end()); int res = 1, now = 1; for(int i = 1; i < v.size(); i++) now = (v[i] == v[i - 1] + 1 ? now + 1 : 1), chmax(res, now); return res; } int inder[maxn], top, ha[maxn], cur, mx; struct node { int x, deg; }s[maxn]; int find(int x) { return fa[x] == x ? x : find(fa[x]); } void unionn(int x, int y) { x = find(x); y = find(y); if(x == y) return; if(inder[x] < inder[y]) swap(x, y); chmax(mx, inder[x] + inder[y]); fa[y] = x; s[++top] = (node) {y, inder[y]}; s[++top] = (node) {x, inder[x]};//tag inder[x] += inder[y]; } void delet(int cur) { while(top > cur) { node pre = s[top--]; fa[pre.x] = pre.x; inder[pre.x] = pre.deg; } } void add(int x) { ha[x] = 1; if(ha[x - 1]) unionn(x - 1, x); if(ha[x + 1]) unionn(x, x + 1); } void solve(int i, vector<q> &v) { memset(ha, 0, sizeof(ha)); top = 0; int r = min(n, i * block) + 1; int ql = r, qr = ql - 1;//tag cur = 0, mx = 1; for(int i = 1; i <= n; i++) fa[i] = i, inder[i] = 1; for(int i = 0; i < v.size(); i++) { q x = v[i]; while(qr < x.r) add(a[++qr]); cur = mx; int pre = top; while(ql > x.l) add(a[--ql]); ans[x.id] = mx; mx = cur; delet(pre); while(ql < r) ha[a[ql++]] = 0; } } signed main() { int mx = 0; n = read(); m = read(); block = sqrt(n); for(int i = 1; i <= n; i++) a[i] = read(), belong[i] = (i - 1) / block + 1, chmax(mx, belong[i]); for(int i = 1; i <= m; i++) { int x = read(), y = read(); if(belong[x] == belong[y]) ans[i] = solveblock(x, y); else q[belong[x]].push_back({x, y, i}); } for(int i = 1; i <= mx; 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; } /* 8 3 3 1 7 2 4 5 8 6 1 6 1 3 2 4 */
上一篇: shared_ptr和动态数组