This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub HyunjaeLee/Algorithms
#include "graph/offline_dynamic_connectivity.hpp"
#ifndef OFFLINE_DYNAMIC_CONNECTIVITY_HPP #define OFFLINE_DYNAMIC_CONNECTIVITY_HPP #include <algorithm> #include <array> #include <cassert> #include <type_traits> #include <utility> #include <vector> template <typename DisjointSet> struct offline_dynamic_connectivity { explicit offline_dynamic_connectivity(int n) : n_(n), timer_(0) {} void toggle_edge(int u, int v) { assert(0 <= u && u < n_ && 0 <= v && v < n_); if (u > v) { std::swap(u, v); } edges_.push_back({u, v, timer_}); } int snapshot() { return timer_++; } void reserve(int n) { edges_.reserve(n); } template <typename Function> std::vector<std::invoke_result_t<Function, DisjointSet, int>> solve(Function f) { auto k = timer_; if (k == 0) { return {}; } std::sort(edges_.begin(), edges_.end()); std::vector<std::vector<std::pair<int, int>>> segment(2 * k); auto edges_size = static_cast<int>(edges_.size()); for (auto i = 0; i < edges_size; ++i) { auto [u, v, l] = edges_[i]; auto r = k; if (i + 1 < edges_size && u == edges_[i + 1][0] && v == edges_[i + 1][1]) { r = edges_[++i][2]; } l += k; r += k; while (l < r) { if (l & 1) { segment[l++].push_back({u, v}); } if (r & 1) { segment[--r].push_back({u, v}); } l >>= 1; r >>= 1; } } DisjointSet dsu(n_); std::vector<std::invoke_result_t<Function, DisjointSet, int>> result(k); auto dfs = [&](auto self, int node) -> void { auto count = 0; for (auto [u, v] : segment[node]) { if (dsu.merge(u, v)) { ++count; } } if (node < k) { self(self, 2 * node); self(self, 2 * node + 1); } else { result[node - k] = f(dsu, node - k); } dsu.rollback(count); }; dfs(dfs, 1); return result; } private: int n_, timer_; std::vector<std::array<int, 3>> edges_; }; #endif // OFFLINE_DYNAMIC_CONNECTIVITY_HPP
#line 1 "graph/offline_dynamic_connectivity.hpp" #include <algorithm> #include <array> #include <cassert> #include <type_traits> #include <utility> #include <vector> template <typename DisjointSet> struct offline_dynamic_connectivity { explicit offline_dynamic_connectivity(int n) : n_(n), timer_(0) {} void toggle_edge(int u, int v) { assert(0 <= u && u < n_ && 0 <= v && v < n_); if (u > v) { std::swap(u, v); } edges_.push_back({u, v, timer_}); } int snapshot() { return timer_++; } void reserve(int n) { edges_.reserve(n); } template <typename Function> std::vector<std::invoke_result_t<Function, DisjointSet, int>> solve(Function f) { auto k = timer_; if (k == 0) { return {}; } std::sort(edges_.begin(), edges_.end()); std::vector<std::vector<std::pair<int, int>>> segment(2 * k); auto edges_size = static_cast<int>(edges_.size()); for (auto i = 0; i < edges_size; ++i) { auto [u, v, l] = edges_[i]; auto r = k; if (i + 1 < edges_size && u == edges_[i + 1][0] && v == edges_[i + 1][1]) { r = edges_[++i][2]; } l += k; r += k; while (l < r) { if (l & 1) { segment[l++].push_back({u, v}); } if (r & 1) { segment[--r].push_back({u, v}); } l >>= 1; r >>= 1; } } DisjointSet dsu(n_); std::vector<std::invoke_result_t<Function, DisjointSet, int>> result(k); auto dfs = [&](auto self, int node) -> void { auto count = 0; for (auto [u, v] : segment[node]) { if (dsu.merge(u, v)) { ++count; } } if (node < k) { self(self, 2 * node); self(self, 2 * node + 1); } else { result[node - k] = f(dsu, node - k); } dsu.rollback(count); }; dfs(dfs, 1); return result; } private: int n_, timer_; std::vector<std::array<int, 3>> edges_; };