library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub yuruhi/library

:heavy_check_mark: test/PersistentUnionFind.test.cpp

Depends on

Code

#define PROBLEM "https://judge.yosupo.jp/problem/persistent_unionfind"
#include "./../DataStructure/PersistentUnionFind.cpp"
#include <iostream>
using namespace std;

int main() {
	cin.tie(nullptr);
	ios_base::sync_with_stdio(false);

	int n, q;
	cin >> n >> q;
	vector<PersistentUnionFind> g(q + 1);
	g[0] = PersistentUnionFind(n);
	for (int i = 1; i <= q; ++i) {
		int com, k, u, v;
		cin >> com >> k >> u >> v;
		k++;
		if (com == 0) {
			g[i] = g[k].unite(u, v).second;
		} else {
			cout << g[k].same(u, v) << '\n';
		}
	}
}
#line 1 "test/PersistentUnionFind.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/persistent_unionfind"
#line 2 "DataStructure/PersistentUnionFind.cpp"
#include <vector>
#include <utility>
#line 2 "DataStructure/PersistentArray.cpp"
#include <array>
#line 4 "DataStructure/PersistentArray.cpp"
#include <memory>

template <class T, std::size_t LOG> class PersistentArray {
public:
	using value_type = T;
	using const_reference = const value_type&;
	static constexpr std::size_t CHILD_SIZE = 1 << LOG;

private:
	struct node_type;
	using node_ptr = std::shared_ptr<node_type>;
	struct node_type {
		value_type value;
		std::array<node_ptr, CHILD_SIZE> child;
	};

	static value_type get(std::size_t i, node_ptr p) {
		if (!p) {
			return value_type();
		} else if (i == 0) {
			return p->value;
		} else {
			return get(i >> LOG, p->child[i & (CHILD_SIZE - 1)]);
		}
	}
	static node_ptr set(std::size_t i, const_reference val, node_ptr p) {
		node_ptr result = p ? std::make_shared<node_type>(*p) : std::make_shared<node_type>();
		if (i == 0) {
			result->value = val;
		} else {
			std::size_t index = i & (CHILD_SIZE - 1);
			result->child[index] = set(i >> LOG, val, result->child[index]);
		}
		return result;
	}
	static void destructive_set(std::size_t i, const_reference val, node_ptr& p) {
		if (!p) {
			p = std::make_shared<node_type>();
		}
		if (i == 0) {
			p->value = val;
		} else {
			std::size_t index = i & (CHILD_SIZE - 1);
			destructive_set(i >> LOG, val, p->child[index]);
		}
	}

	node_ptr root;
	PersistentArray(node_ptr _root) : root(_root) {}

public:
	PersistentArray() : root() {}
	PersistentArray(const std::vector<value_type>& v) : root() {
		for (std::size_t i = 0; i < v.size(); ++i) {
			destructive_set(i, v[i]);
		}
	}
	value_type get(std::size_t i) const {
		return get(i, root);
	}
	value_type operator[](std::size_t i) const {
		return get(i);
	}
	std::vector<value_type> to_a(std::size_t n) const {
		std::vector<value_type> result(n);
		for (std::size_t i = 0; i < n; ++i) {
			result[i] = get(i);
		}
		return result;
	}
	PersistentArray set(std::size_t i, const_reference val) const {
		return PersistentArray(set(i, val, root));
	}
	void destructive_set(std::size_t i, const_reference val) {
		destructive_set(i, val, root);
	}
};
#line 5 "DataStructure/PersistentUnionFind.cpp"

class PersistentUnionFind {
	using data_type = PersistentArray<int, 2>;

public:
	data_type data;
	PersistentUnionFind(const data_type& _data) : data(_data) {}

	PersistentUnionFind() = default;
	PersistentUnionFind(int n) : data(std::vector(n, -1)) {}
	int root(int k) const {
		int p = data[k];
		return p >= 0 ? root(p) : k;
	}
	bool same(int u, int v) const {
		return root(u) == root(v);
	}
	int size(int k) const {
		return -data[root(k)];
	}
	std::pair<bool, PersistentUnionFind> unite(int x, int y) {
		x = root(x);
		y = root(y);
		if (x == y) {
			return {false, *this};
		}
		if (data[x] > data[y]) {
			std::swap(x, y);
		}
		return {true, data.set(x, data[x] + data[y]).set(y, x)};
	}
};
#line 3 "test/PersistentUnionFind.test.cpp"
#include <iostream>
using namespace std;

int main() {
	cin.tie(nullptr);
	ios_base::sync_with_stdio(false);

	int n, q;
	cin >> n >> q;
	vector<PersistentUnionFind> g(q + 1);
	g[0] = PersistentUnionFind(n);
	for (int i = 1; i <= q; ++i) {
		int com, k, u, v;
		cin >> com >> k >> u >> v;
		k++;
		if (com == 0) {
			g[i] = g[k].unite(u, v).second;
		} else {
			cout << g[k].same(u, v) << '\n';
		}
	}
}
Back to top page