洛谷P2056 [ZJOI2007] 捉迷藏 题解 动态点分治/点分树
思路全部来自 OI WIKI:https://oi.wiki/graph/dynamic-tree-divide/
按照自己的码风写了一下。
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int n, Q, rt, fa[maxn], lit[maxn], lit_cnt;
bool vis[maxn];
vector<int> g[maxn];
struct LCA {
int dep[maxn], fa[maxn][17];
void dfs(int u, int p) {
fa[u][0] = p;
dep[u] = dep[p] + 1;
for (auto v : g[u])
if (v != p)
dfs(v, u);
}
void build() {
dfs(1, 0);
for (int i = 1; i < 17; i++)
for (int u = 1; u <= n; u++)
fa[u][i] = fa[ fa[u][i-1] ][i-1];
}
int lca(int x, int y) {
if (dep[x] < dep[y])
swap(x, y);
for (int i = 16; i >= 0; i--) {
int p = fa[x][i];
if (dep[p] >= dep[y]) x = p;
}
if (x == y)
return x;
for (int i = 16; i >= 0; i--)
if (fa[x][i] != fa[y][i])
x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
int dis(int x, int y) {
return dep[x] + dep[y] - 2 * dep[lca(x, y)];
}
} lca;
struct Heap {
priority_queue<int> a, b;
void push(int x) {
a.push(x);
}
void del(int x) {
b.push(x);
}
int top() {
while (!b.empty() && a.top() == b.top()) a.pop(), b.pop();
return a.top();
}
void pop() {
while (!b.empty() && a.top() == b.top()) a.pop(), b.pop();
a.pop();
}
int size() {
return a.size() - b.size();
}
int top2() { // 最大的两个数之和
int tmp = top(), res = tmp;
pop();
res += top();
push(tmp);
return res;
}
} heap_fa[maxn], heap_me[maxn], ans;
int get_sz(int u, int p) {
if (vis[u]) return 0;
int sz = 1;
for (auto v : g[u])
if (v != p)
sz += get_sz(v, u);
return sz;
}
int get_wc(int u, int p, int tot, int &wc) {
if (vis[u]) return 0;
int sz = 1, mx = 0;
for (auto v : g[u]) {
if (v != p) {
int tmp = get_wc(v, u, tot, wc);
sz += tmp;
mx = max(mx, tmp);
}
}
mx = max(mx, tot - sz);
if (mx <= tot / 2)
wc = u;
return sz;
}
void dfs_fa(int u, int p, int d, int x) {
if (vis[u]) return;
heap_fa[x].push(d);
for (auto v : g[u])
if (v != p)
dfs_fa(v, u, d+1, x);
}
void pre(int u) {
heap_me[u].push(0);
vis[u] = true;
for (auto v : g[u]) {
if (vis[v]) continue;
int x;
get_wc(v, u, get_sz(v, u), x);
dfs_fa(v, u, 1, x);
heap_me[u].push(heap_fa[x].top());
fa[x] = u;
pre(x);
}
if (heap_me[u].size() >= 2)
ans.push(heap_me[u].top2());
}
int main() {
scanf("%d", &n);
for (int i = 1, u, v; i < n; i++) {
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
lca.build();
get_wc(1, 0, n, rt);
pre(rt);
scanf("%d", &Q);
while (Q--) {
char op[2];
scanf("%s", op);
if (op[0] == 'G') {
if (lit_cnt == n) puts("-1");
else if (lit_cnt == n-1) puts("0");
else printf("%d\n", ans.top());
}
else {
int x;
scanf("%d", &x);
if (!lit[x]) {
lit_cnt++;
if (heap_me[x].size() >= 2)
ans.del(heap_me[x].top2());
heap_me[x].del(0);
if (heap_me[x].size() >= 2)
ans.push(heap_me[x].top2());
for (int u = x; fa[u]; u = fa[u]) {
int p = fa[u];
if (heap_me[p].size() >= 2)
ans.del(heap_me[p].top2());
heap_me[p].del(heap_fa[u].top());
heap_fa[u].del(lca.dis(p, x));
if (heap_fa[u].size() >= 1)
heap_me[p].push(heap_fa[u].top());
if (heap_me[p].size() >= 2)
ans.push(heap_me[p].top2());
}
}
else {
lit_cnt--;
if (heap_me[x].size() >= 2)
ans.del(heap_me[x].top2());
heap_me[x].push(0);
if (heap_me[x].size() >= 2)
ans.push(heap_me[x].top2());
for (int u = x; fa[u]; u = fa[u]) {
int p = fa[u];
if (heap_me[p].size() >= 2)
ans.del(heap_me[p].top2());
if (heap_fa[u].size() >= 1)
heap_me[p].del(heap_fa[u].top());
heap_fa[u].push(lca.dis(p, x));
heap_me[p].push(heap_fa[u].top());
if (heap_me[p].size() >= 2)
ans.push(heap_me[p].top2());
}
}
lit[x] ^= 1;
}
}
return 0;
}
浙公网安备 33010602011771号