Skip to content

Commit

Permalink
add: monoid-unionfind
Browse files Browse the repository at this point in the history
  • Loading branch information
shogo314 committed Jan 15, 2025
1 parent ba7503a commit 175f5f1
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 2 deletions.
46 changes: 46 additions & 0 deletions cpp/monoid-unionfind.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma once

/**
* @file monoid-unionfind.hpp
* @brief 可換モノイドを乗せるUnionFind
*/

#include "unionfind.hpp"

/**
* @brief 可換モノイドを乗せるUnionFind
*
* @tparam S
* @tparam Op
*/
template <typename S, class Op>
class MonoidUnionFind : private UnionFind {
private:
std::vector<S> val;
using UnionFind::_n;
using UnionFind::parent_or_size;

public:
inline constexpr static auto op = Op();

explicit MonoidUnionFind(std::vector<S> v) : UnionFind(v.size()), val(v) {}
MonoidUnionFind(int n, S e) : UnionFind(n), val(n, e) {}
using UnionFind::groups;
using UnionFind::leader;
using UnionFind::same;
using UnionFind::size;
int merge(int a, int b) {
assert(0 <= a && a < _n);
assert(0 <= b && b < _n);
int x = leader(a), y = leader(b);
if (x == y) return x;
if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
parent_or_size[x] += parent_or_size[y];
parent_or_size[y] = x;
val[x] = op(val[x], val[y]);
return x;
}
const S& prod(int a) {
return val[leader(a)];
}
};
4 changes: 2 additions & 2 deletions cpp/unionfind.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* @brief 無向グラフに対して「辺の追加」、「2頂点が連結かの判定」をする
*/
struct UnionFind {
private:
protected:
int _n;
// 負ならサイズ、非負なら親
std::vector<int> parent_or_size;
Expand Down Expand Up @@ -91,4 +91,4 @@ struct UnionFind {
result.end());
return result;
}
};
};
53 changes: 53 additions & 0 deletions test/yukicoder-674.test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#define PROBLEM "https://yukicoder.me/problems/no/674"

Check failure on line 1 in test/yukicoder-674.test.cpp

View workflow job for this annotation

GitHub Actions / verify

failed to verify

#include "../cpp/monoid-unionfind.hpp"
#include "../cpp/more_functional.hpp"

#include <iostream>
#include <set>

using ll = long long;

int main() {
ll D, Q;
std::cin >> D >> Q;
std::vector<std::pair<ll, ll>> AB(Q);
std::set<ll> s;
for (auto& [A, B] : AB) {
std::cin >> A >> B;
s.insert(A);
s.insert(A - 1);
s.insert(B);
s.insert(B + 1);
}
std::vector<ll> v(s.begin(), s.end());
std::vector<bool> f(s.size());
std::vector<std::pair<int, int>> init;
for (std::size_t i = 0; i < v.size(); i++) {
init.push_back({i, i});
}
MonoidUnionFind<std::pair<int, int>, more_functional::MinMax<int>> uf(init);
ll ans = 0;
for (auto [A, B] : AB) {
int k = std::lower_bound(v.begin(), v.end(), A) - v.begin();
std::pair<int, int> p = uf.prod(k);
while (v[p.second + 1] <= B) {
uf.merge(k, p.second + 1);
k = p.second + 1;
p = uf.prod(k);
}
if (f[p.first - 1]) {
uf.merge(p.first - 1, p.first);
}
if (f[p.second + 1]) {
uf.merge(p.second, p.second + 1);
}
f[p.first] = true;
f[p.second] = true;
p = uf.prod(k);
if (ans < v[p.second] - v[p.first] + 1) {
ans = v[p.second] - v[p.first] + 1;
}
std::cout << ans << std::endl;
}
}

0 comments on commit 175f5f1

Please sign in to comment.