Skip to content

add simple mo method to hilbert order mos #376

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions other_algorithms/hilbert_order_mos.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ std::vector<int> sort_by_hilbert_order(const std::vector<std::pair<Int, Int>> &p
// Mo's algorithm with Hilbert order
// - add(x, y) : Add (x, y) as query.
// - run(IncX, DecX, IncY, DecY, Query) : run Mo's algorithm.
// - run(Add, Remove, Query) : run Mo's algorithm with Add, Remove, and Query functions. add(x, y) means [x, y).
struct MosAlgorithmHilbertOrder {
int cx, cy;
std::vector<std::pair<int, int>> queries;
Expand All @@ -79,4 +80,9 @@ struct MosAlgorithmHilbertOrder {
query(q);
}
}

template <typename F1, typename F3, typename F5> void run(F1 Add, F3 Remove, F5 Query) {
run([&](int x, int) { Remove(x); }, [&](int, int x) { Add(x); },
[&](int y, int) { Add(y); }, [&](int, int y) { Remove(y); }, Query);
}
};
18 changes: 18 additions & 0 deletions other_algorithms/hilbert_order_mos.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Mo's algorithm の一種で,2 次元平面上の点として表現可能なク

## 使用方法

### 一般の 2 次元平面上の点クエリの場合

```cpp
vector<Result> ret(Q); // 答えを格納する領域
int x_init = 0, y_init = 0;
Expand All @@ -26,9 +28,25 @@ mo.run(inc_x, dec_x, inc_y, dec_y, solve);
for (auto ans : ret) cout << ans << '\n';
```

### 特に半開区間 $[l, r)$ クエリで区間の左右の伸張・収縮が同一の関数で書ける場合

```cpp
MosAlgorithmHilbertOrder mos(0, 0);
for (auto [l, r] : queries) {
mos.add(l, r);
}

mos.run(
[&](int i) { /* Add i */ },
[&](int i) { /* Remove i */ },
[&](int q) { /* ret.at(q) = get_solution(); */ }
);
```

## 問題例

- [AtCoder Beginner Contest 384 G - Abs Sum](https://atcoder.jp/contests/abc384/tasks/abc384_g)
- [AtCoder Beginner Contest 405 G - Range Shuffle Query](https://atcoder.jp/contests/abc405/tasks/abc405_g)

## Links

Expand Down