|
| 1 | +--- |
| 2 | +title: 3D points to Hilbert order, used for Mo with update (3 次元空間の点の Hilbert order への変換, Mo's algorithm (「時空間 Mo」)への応用) |
| 3 | +documentation_of: ./hilbert_order_mos_3d.hpp |
| 4 | +--- |
| 5 | + |
| 6 | +点 $(x, y, z)$ の 3 次元のヒルベルト曲線上の端点からの距離を計算する. |
| 7 | + |
| 8 | +コンテストでの応用上重要な特徴として,座標の値が $n$ 以下の $q$ 個の点列をこの値をキーにソートする(ヒルベルトソート)ことで,パスのマンハッタン距離の総和が $O(n q^{2/3})$ で抑えられる. |
| 9 | + |
| 10 | +Mo with update などの用途でクエリ処理順序の決定に利用可能で,例えば更新ありの Mo's algorithm は $O(n q^{2/3})$ で解けることになる. |
| 11 | + |
| 12 | +## 使用方法 |
| 13 | + |
| 14 | +```cpp |
| 15 | +unsigned x, y, z; |
| 16 | +unsigned long long h = encode_hilbert_order_3d<unsigned long long>(x, y, z); |
| 17 | +``` |
| 18 | + |
| 19 | +### Mo with update への応用 |
| 20 | + |
| 21 | +長さ $n$ の列と $q$ 個のクエリが与えられて, $x, y$ が区間の両端 $l, r$ に対応し, $z$ が更新時刻 $t$ に対応するタイプの問題は,特に以下のようなコードで処理できる.なおこの手の出題ではジャッジが $O(nq)$ と $O(n q^{2/3})$ を区別する必要があるため,定数倍の実装には気をつけた方がよい. |
| 22 | + |
| 23 | +#### クエリ情報・更新情報取得 |
| 24 | + |
| 25 | +```cpp |
| 26 | +int tick = 0; |
| 27 | +vector<tuple<unsigned long long, int, int, int, int>> queries; |
| 28 | +vector<tuple<int, int, int>> updates; |
| 29 | + |
| 30 | +for (int q = 0; q < Q; ++q) { |
| 31 | + int tp, l, r, p, x; |
| 32 | + cin >> tp; |
| 33 | + if (tp == 1) { |
| 34 | + cin >> l >> r; |
| 35 | + --l; |
| 36 | + const int nq = queries.size(); |
| 37 | + queries.emplace_back(encode_hilbert_order_3d<unsigned long long>(tick, l, r), l, r, tick, nq); |
| 38 | + } else { |
| 39 | + cin >> p >> x; |
| 40 | + --p; |
| 41 | + updates.emplace_back(p, A.at(p), x); |
| 42 | + A.at(p) = x; |
| 43 | + ++tick; |
| 44 | + } |
| 45 | +} |
| 46 | +``` |
| 47 | + |
| 48 | +#### 解取得処理の実行 |
| 49 | + |
| 50 | +```cpp |
| 51 | +sort(queries.begin(), queries.end()); |
| 52 | + |
| 53 | +int l = 0, r = 0; |
| 54 | + |
| 55 | +vector<int> vcnt(zs.size()); // 区間に現れる各値の計数 |
| 56 | +vector<int> vhist(N + 2); // 配列 vcnt の頻度分布 |
| 57 | +vhist.at(0) = vcnt.size(); |
| 58 | + |
| 59 | +auto add_val = [&](int v) -> void { |
| 60 | + const int cnt = vcnt[v]; |
| 61 | + vcnt[v]++; |
| 62 | + vhist[cnt]--; |
| 63 | + vhist[cnt + 1]++; |
| 64 | +}; |
| 65 | + |
| 66 | +auto remove_val = [&](int v) -> void { |
| 67 | + --vcnt[v]; |
| 68 | + const int cnt = vcnt[v]; |
| 69 | + vhist[cnt]++; |
| 70 | + vhist[cnt + 1]--; |
| 71 | +}; |
| 72 | + |
| 73 | +vector<int> ret(queries.size(), -1); |
| 74 | + |
| 75 | +for (const auto &[_, ltgt, rtgt, ticktgt, nq] : queries) { |
| 76 | + while (tick < ticktgt) { |
| 77 | + auto [p, oldval, newval] = updates[tick]; |
| 78 | + A[p] = newval; |
| 79 | + if (l <= p and p < r) { |
| 80 | + remove_val(oldval); |
| 81 | + add_val(newval); |
| 82 | + } |
| 83 | + ++tick; |
| 84 | + } |
| 85 | + |
| 86 | + while (tick > ticktgt) { |
| 87 | + --tick; |
| 88 | + auto [p, oldval, newval] = updates[tick]; |
| 89 | + A[p] = oldval; |
| 90 | + if (l <= p and p < r) { |
| 91 | + remove_val(newval); |
| 92 | + add_val(oldval); |
| 93 | + } |
| 94 | + } |
| 95 | + |
| 96 | + while (ltgt < l) add_val(A[--l]); |
| 97 | + |
| 98 | + while (r < rtgt) add_val(A[r++]); |
| 99 | + |
| 100 | + while (l < ltgt) remove_val(A[l++]); |
| 101 | + |
| 102 | + while (rtgt < r) remove_val(A[--r]); |
| 103 | + |
| 104 | + /* solve subproblem |
| 105 | + ret.at(nq) = ***; |
| 106 | + */ |
| 107 | +} |
| 108 | +``` |
| 109 | +
|
| 110 | +## 問題例 |
| 111 | +
|
| 112 | +列の要素更新ありの Mo's algorithm が必要な問題例を以下に挙げる. |
| 113 | +
|
| 114 | +- [Codeforces Round 466 (Div. 2) F. Machine Learning - Codeforces](https://codeforces.com/contest/940/problem/F) |
| 115 | +- [Educational Codeforces Round 103 (Rated for Div. 2) G. Minimum Difference - Codeforces](https://codeforces.com/contest/1476/problem/G) |
| 116 | +- [Primitive Queries \| CodeChef](https://www.codechef.com/problems/DISTNUM3) |
| 117 | + - 木のパスクエリ処理・要素更新ありの Mo's algorithm で解ける. |
| 118 | +
|
| 119 | +## Links |
| 120 | +
|
| 121 | +- [An alternative sorting order for Mo's algorithm - Codeforces](https://codeforces.com/blog/entry/61203) |
| 122 | +- [Mo's algorithm - アルゴリズムとデータ構造大全](https://take44444.github.io/Algorithm-Book/range/mo/main.html) |
| 123 | +- [[2308.05673] Algorithms for Encoding and Decoding 3D Hilbert Orderings](https://arxiv.org/abs/2308.05673) |
0 commit comments