This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub hitonanode/cplib-cpp
#include "unionfind/fully_persistent_uf.hpp"
#pragma once #include "../data_structure/persistent_array.hpp" #include <vector> // CUT begin // Fully persistent UnionFind // - find(t, x) : find the root of DSU tree x belongs to, when unite() is called t times. // Complexity: O(logN) for each query // Reference: <https://ei1333.github.io/library/structure/union-find/persistent-union-find.cpp> struct PersistentUnionFind { int N; using Array = persistent_array<int, 4>; Array par; std::vector<Array::node *> savepoints; // Tree structure is saved after every `unite()` operation PersistentUnionFind(int N) : N(N), par(-1) { savepoints.emplace_back(nullptr); } int find(int t, int x) const { const int p = par.get(savepoints[t], x); return p < 0 ? x : find(t, p); } bool unite(int t, int x, int y) { x = find(t, x), y = find(t, y); auto ptr = savepoints[t]; if (x != y) { int sz_x = -par.get(savepoints[t], x), sz_y = -par.get(savepoints[t], y); if (sz_x > sz_y) { par.ch(ptr, x, -sz_x - sz_y), par.ch(ptr, y, x); } else { par.ch(ptr, y, -sz_x - sz_y), par.ch(ptr, x, y); } } return savepoints.emplace_back(ptr), x != y; } int count(int t, int x) const { return -par.get(savepoints[t], find(t, x)); } bool same(int t, int x, int y) const { return find(t, x) == find(t, y); } };
#line 2 "data_structure/persistent_array.hpp" #include <algorithm> #include <array> #include <vector> // CUT begin // Persistent Array // Reference: <https://qiita.com/hotman78/items/9c643feae1de087e6fc5> // <https://ei1333.github.io/luzhiled/snippets/structure/persistent-array.html> // - (2^LOG)-ary tree-based // - Fully persistent // - `get(root, k)`: get k-th element // - `set(root, k, data)`: make new array whose k-th element is updated to data // - `ch(root, k, data)` : change k-th element and implicitly update root // Verify: Codeforces 707D <https://codeforces.com/contest/707/problem/D> template <typename T, int LOG> struct persistent_array { T zero; struct node { T data; std::array<node *, 1 << LOG> child; node(const T &d) : data(d) { std::fill(child.begin(), child.end(), nullptr); } node(const node &n) : data(n.data) { std::copy(n.child.begin(), n.child.end(), child.begin()); } }; persistent_array(T zero) : zero(zero) {} T get(node *t, int k) const { if (t == nullptr) { return zero; } return k ? get(t->child[k & ((1 << LOG) - 1)], k >> LOG) : t->data; } [[nodiscard]] node *set(node *t, int k, const T &data) { t = (t == nullptr) ? new node(zero) : new node(*t); if (k == 0) { t->data = data; } else { auto ptr = set(t->child[k & ((1 << LOG) - 1)], k >> LOG, data); t->child[k & ((1 << LOG) - 1)] = ptr; } return t; } void ch(node *&t, int k, const T &data) { t = set(t, k, data); } [[nodiscard]] node *build(const std::vector<T> &vec) { node *root = nullptr; for (size_t i = 0; i < vec.size(); i++) { root = set(root, i, vec[i]); } return root; } }; #line 4 "unionfind/fully_persistent_uf.hpp" // CUT begin // Fully persistent UnionFind // - find(t, x) : find the root of DSU tree x belongs to, when unite() is called t times. // Complexity: O(logN) for each query // Reference: <https://ei1333.github.io/library/structure/union-find/persistent-union-find.cpp> struct PersistentUnionFind { int N; using Array = persistent_array<int, 4>; Array par; std::vector<Array::node *> savepoints; // Tree structure is saved after every `unite()` operation PersistentUnionFind(int N) : N(N), par(-1) { savepoints.emplace_back(nullptr); } int find(int t, int x) const { const int p = par.get(savepoints[t], x); return p < 0 ? x : find(t, p); } bool unite(int t, int x, int y) { x = find(t, x), y = find(t, y); auto ptr = savepoints[t]; if (x != y) { int sz_x = -par.get(savepoints[t], x), sz_y = -par.get(savepoints[t], y); if (sz_x > sz_y) { par.ch(ptr, x, -sz_x - sz_y), par.ch(ptr, y, x); } else { par.ch(ptr, y, -sz_x - sz_y), par.ch(ptr, x, y); } } return savepoints.emplace_back(ptr), x != y; } int count(int t, int x) const { return -par.get(savepoints[t], find(t, x)); } bool same(int t, int x, int y) const { return find(t, x) == find(t, y); } };