232's competitive-programming templates.
OfflineDynamicConnectivity
232-aka-pretty-pi
2024. 9. 16. 18:03
need RollBackUnionFind
struct OfflineDynamicConnectivity {
int n;
std::vector<std::array<int, 4>> edges;
OfflineDynamicConnectivity(int n) : n(n) {
assert(n > 0);
}
void addEdge(int l, int r, int u, int v) {
assert(0 <= u && u < n && 0 <= v && v < n);
edges.push_back({l, r, u, v});
}
[[nodiscard]] std::vector<bool> solve(const std::vector<std::pair<int, int>>& qrs) const {
int q = int(qrs.size());
assert(q > 0);
std::vector<std::vector<std::pair<int, int>>> seg(2 * q - 1);
for (const auto& [l, r, u, v] : edges) {
assert(0 <= l && l <= r && r <= q);
if (l == r) {
continue;
}
auto dfs = [&](auto&& dfs, int x, int xl, int xr) -> void {
if (l <= xl && xr <= r) {
seg[x].emplace_back(u, v);
return;
}
int xm = xl + (xr - xl) / 2;
if (l < xm) {
dfs(dfs, x + 1, xl, xm);
}
if (xm < r) {
dfs(dfs, x + 2 * (xm - xl), xm, xr);
}
};
dfs(dfs, 0, 0, q);
}
RollBackUnionFind rbuf(n);
std::vector<bool> res(q);
auto dfs = [&](auto&& dfs, int x, int l, int r) -> void {
for (const auto& [u, v] : seg[x]) {
rbuf.unite(u, v);
}
if (r - l == 1) {
res[l] = (rbuf.find(qrs[l].first) == rbuf.find(qrs[l].second));
} else {
int m = l + (r - l) / 2;
dfs(dfs, x + 1, l, m);
dfs(dfs, x + 2 * (m - l), m, r);
}
rbuf.rollBack(seg[x].size());
};
dfs(dfs, 0, 0, q);
return res;
}
};