HDU 6271 Master of Connected Component(2017 CCPC 杭州 H题,树分块 + 并查集的撤销)
Posted cxhscst2
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 6271 Master of Connected Component(2017 CCPC 杭州 H题,树分块 + 并查集的撤销)相关的知识,希望对你有一定的参考价值。
题目链接 2017 CCPC Hangzhou Problem H
思路:对树进行分块。把第一棵树分成$sqrt{n}$块,第二棵树也分成$sqrt{n}$块。
分块的时候满足每个块是一个连通块,那么每个块就有一个共同的祖先。
把询问按照第一个点被第一棵树的哪个祖先管辖和第二个点被第二棵树的哪个祖先管辖,分成$n$类。
每一类询问一起处理,处理完后用可撤销并查集恢复到之前的状态。
每一类询问之间依次转移,每次转移,移动次数不会超过$sqrt{n}$次。
最后总时间复杂度$O(n^{1.5}logn)$
#include <map> #include <set> #include <cmath> #include <ctime> #include <queue> #include <stack> #include <bitset> #include <cstdio> #include <string> #include <vector> #include <cassert> #include <cstring> #include <fstream> #include <sstream> #include <utility> #include <iostream> #include <algorithm> #include <unordered_map> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) #define MP make_pair #define fi first #define se second typedef long long LL; const int N = 1e4 + 10; const int M = 505; struct node{ int x, y, id; } s[N << 5]; int T; int n, m; int top; int fa1[N], fa2[N], bs; int id1[N], id2[N]; int re[M][M]; int father[N], sz[N]; int ans; int ret[N]; int ux[N], uy[N], vx[N], vy[N]; vector <int> v[N], v1, v2; vector <node> q[M][M]; void dfs1(int x, int fa, int dep){ fa1[x] = fa; id1[x] = -1; if (dep % bs == 0){ id1[x] = v1.size(); v1.push_back(x); } for (auto u : v[x]){ if (u == fa) continue; dfs1(u, x, dep + 1); } } void dfs2(int x, int fa, int dep){ fa2[x] = fa; id2[x] = -1; if (dep % bs == 0){ id2[x] = v2.size(); v2.push_back(x); } for (auto u : v[x]){ if (u == fa) continue; dfs2(u, x, dep + 1); } } void merge_(int x, int y){ while (x != father[x]) x = father[x]; while (y != father[y]) y = father[y]; if (x == y) return; if (sz[x] > sz[y]) swap(x, y); s[++top] = {x, y}; father[x] = y; --ans; sz[y] += sz[x]; } void recover(int x, int y){ while (top > re[id1[x]][id2[y]]){ auto u = s[top--]; ++ans; father[u.x] = u.x; father[u.y] = u.y; sz[u.y] -= sz[u.x]; } } void commit(int x, int y){ int tx = x, ty = y; for (; id1[tx] == -1; tx = fa1[tx]){} for (; id2[ty] == -1; ty = fa2[ty]){} recover(tx, ty); while (x != tx){ merge_(ux[x], vx[x]); x = fa1[x]; } while (y != ty){ merge_(uy[y], vy[y]); y = fa2[y]; } } int main(){ scanf("%d", &T); while (T--){ scanf("%d%d", &n, &m); rep(i, 1, n) scanf("%d%d", ux + i, vx + i); bs = sqrt(n); rep(i, 0, n + 1) v[i].clear(); rep(i, 2, n){ int x, y; scanf("%d%d", &x, &y); v[x].push_back(y); v[y].push_back(x); } v1.clear(); dfs1(1, 0, 0); rep(i, 0, n + 1) v[i].clear(); rep(i, 1, n) scanf("%d%d", uy + i, vy + i); rep(i, 2, n){ int x, y; scanf("%d%d", &x, &y); v[x].push_back(y); v[y].push_back(x); } v2.clear(); dfs2(1, 0, 0); rep(i, 1, n){ int u, v, x, y; u = v = i; x = u, y = v; for (; id1[x] == -1; x = fa1[x]){} for (; id2[y] == -1; y = fa2[y]){} q[id1[x]][id2[y]].push_back({u, v, i}); } rep(i, 1, m) father[i] = i, sz[i] = 1; ans = m; merge_(ux[1], vx[1]); merge_(uy[1], vy[1]); re[0][0] = (top = 0); for (auto x : v1){ for (auto y : v2){ if (x == 1 && y == 1){ merge_(ux[x], vx[x]); merge_(uy[y], vy[y]); } else if (y == 1){ commit(fa1[x], y); merge_(ux[x], vx[x]); } else{ commit(x, fa2[y]); merge_(uy[y], vy[y]); } re[id1[x]][id2[y]] = top; for (auto u : q[id1[x]][id2[y]]){ commit(u.x, u.y); ret[u.id] = ans; } q[id1[x]][id2[y]].clear(); } } rep(i, 1, n) printf("%d ", ret[i]); } return 0; }
以上是关于HDU 6271 Master of Connected Component(2017 CCPC 杭州 H题,树分块 + 并查集的撤销)的主要内容,如果未能解决你的问题,请参考以下文章
hdu 6268 Master of Subgraph(点分治+bitset)
HDU 6274 Master of Sequence (暴力+下整除)