ウェーブレット行列の共通コア(各 level のビットベクトル型を差し替え可能にする)
lib/internal/wavelet_matrix_base.hpp
インクルード
#include "internal/wavelet_matrix_base.hpp"
内部実装
直接使うことは想定していないが、公開 API の基底として現れる。
| 名前 | 説明 |
|---|---|
WaveletMatrixCore |
ウェーブレット行列の共通コア(各 level のビットベクトル型を差し替え可能にする) |
このヘッダを使うライブラリ(4)
-
要素の挿入・削除が可能な動的ウェーブレット行列
lib/data_structure/dynamic_wavelet_matrix.hpp -
区間 [l, r) について sum(min(A_i, x)) / sum(max(A_i, x)) を求める
lib/data_structure/range_min_max_sum.hpp -
ウェーブレット行列
lib/data_structure/wavelet_matrix.hpp -
キー区間に含まれる重みの総和も扱うウェーブレット行列
lib/data_structure/wavelet_matrix_rectangle_sum.hpp
検証プログラム(6)
-
test/aoj/challenge/2270.test.cpp
test/aoj/challenge/2270.test.cpp -
test/yosupo/data_structure/point_set_range_frequency.test.cpp
test/yosupo/data_structure/point_set_range_frequency.test.cpp -
test/yosupo/data_structure/range_kth_smallest.test.cpp
test/yosupo/data_structure/range_kth_smallest.test.cpp -
test/yosupo/data_structure/rectangle_sum.test.cpp
test/yosupo/data_structure/rectangle_sum.test.cpp -
test/yosupo/data_structure/static_range_frequency.test.cpp
test/yosupo/data_structure/static_range_frequency.test.cpp -
test/yukicoder/2065.test.cpp
test/yukicoder/2065.test.cpp
実装
#pragma once
#include <cassert>
#include <tuple>
#include <utility>
namespace internal {
/// @brief ウェーブレット行列の共通コア(各 level のビットベクトル型を差し替え可能にする)
template <class BitVector, class T, int L>
struct WaveletMatrixCore {
T access(int k) const {
T res = 0;
for (int level = L - 1; level >= 0; --level) {
bool f = matrix[level][k];
if (f) res |= T(1) << level;
k = matrix[level].rank(f, k) + mid[level] * f;
}
return res;
}
T operator[](int k) const { return access(k); }
/// count i s.t. `(0 <= i < r) && v[i] == x`
int rank(int r, T x) const {
int l = 0;
for (int level = L - 1; level >= 0; --level) std::tie(l, r) = succ((x >> level) & 1, l, r, level);
return r - l;
}
/// count i s.t. `(l <= i < r) && v[i] == x`
int rank(int l, int r, T x) const { return rank(r, x) - rank(l, x); }
/// k-th smallest number in v[l ... r-1]
T kth_smallest(int l, int r, int k) const {
assert(0 <= k && k < r - l);
T res = 0;
for (int level = L - 1; level >= 0; --level) {
int cnt = matrix[level].rank(false, r) - matrix[level].rank(false, l);
bool f = cnt <= k;
if (f) {
res |= T(1) << level;
k -= cnt;
}
std::tie(l, r) = succ(f, l, r, level);
}
return res;
}
/// k-th largest number in v[l ... r-1]
T kth_largest(int l, int r, int k) const { return kth_smallest(l, r, r - l - k - 1); }
/// count i s.t. `(l <= i < r) && (v[i] < upper)`
int range_freq(int l, int r, T upper) const {
int res = 0;
for (int level = L - 1; level >= 0; --level) {
bool f = ((upper >> level) & 1);
if (f) res += matrix[level].rank(false, r) - matrix[level].rank(false, l);
std::tie(l, r) = succ(f, l, r, level);
}
return res;
}
/// count i s.t. `(l <= i < r) && (lower <= v[i] < upper)`
int range_freq(int l, int r, T lower, T upper) const { return range_freq(l, r, upper) - range_freq(l, r, lower); }
/// max v[i] s.t. `(l <= i < r) && (v[i] < upper)`
T prev_value(int l, int r, T upper) const {
int cnt = range_freq(l, r, upper);
return cnt == 0 ? T(-1) : kth_smallest(l, r, cnt - 1);
}
/// min v[i] s.t. `(l <= i < r) && (lower <= v[i])`
T next_value(int l, int r, T lower) const {
int cnt = range_freq(l, r, lower);
return cnt == r - l ? T(-1) : kth_smallest(l, r, cnt);
}
protected:
int length;
BitVector matrix[L];
int mid[L];
std::pair<int, int> succ(bool f, int l, int r, int level) const {
return {matrix[level].rank(f, l) + mid[level] * f, matrix[level].rank(f, r) + mid[level] * f};
}
};
} // namespace internal
bundled
#line 2 "lib/internal/wavelet_matrix_base.hpp"
#include <cassert>
#include <tuple>
#include <utility>
namespace internal {
/// @brief ウェーブレット行列の共通コア(各 level のビットベクトル型を差し替え可能にする)
template <class BitVector, class T, int L>
struct WaveletMatrixCore {
T access(int k) const {
T res = 0;
for (int level = L - 1; level >= 0; --level) {
bool f = matrix[level][k];
if (f) res |= T(1) << level;
k = matrix[level].rank(f, k) + mid[level] * f;
}
return res;
}
T operator[](int k) const { return access(k); }
/// count i s.t. `(0 <= i < r) && v[i] == x`
int rank(int r, T x) const {
int l = 0;
for (int level = L - 1; level >= 0; --level) std::tie(l, r) = succ((x >> level) & 1, l, r, level);
return r - l;
}
/// count i s.t. `(l <= i < r) && v[i] == x`
int rank(int l, int r, T x) const { return rank(r, x) - rank(l, x); }
/// k-th smallest number in v[l ... r-1]
T kth_smallest(int l, int r, int k) const {
assert(0 <= k && k < r - l);
T res = 0;
for (int level = L - 1; level >= 0; --level) {
int cnt = matrix[level].rank(false, r) - matrix[level].rank(false, l);
bool f = cnt <= k;
if (f) {
res |= T(1) << level;
k -= cnt;
}
std::tie(l, r) = succ(f, l, r, level);
}
return res;
}
/// k-th largest number in v[l ... r-1]
T kth_largest(int l, int r, int k) const { return kth_smallest(l, r, r - l - k - 1); }
/// count i s.t. `(l <= i < r) && (v[i] < upper)`
int range_freq(int l, int r, T upper) const {
int res = 0;
for (int level = L - 1; level >= 0; --level) {
bool f = ((upper >> level) & 1);
if (f) res += matrix[level].rank(false, r) - matrix[level].rank(false, l);
std::tie(l, r) = succ(f, l, r, level);
}
return res;
}
/// count i s.t. `(l <= i < r) && (lower <= v[i] < upper)`
int range_freq(int l, int r, T lower, T upper) const { return range_freq(l, r, upper) - range_freq(l, r, lower); }
/// max v[i] s.t. `(l <= i < r) && (v[i] < upper)`
T prev_value(int l, int r, T upper) const {
int cnt = range_freq(l, r, upper);
return cnt == 0 ? T(-1) : kth_smallest(l, r, cnt - 1);
}
/// min v[i] s.t. `(l <= i < r) && (lower <= v[i])`
T next_value(int l, int r, T lower) const {
int cnt = range_freq(l, r, lower);
return cnt == r - l ? T(-1) : kth_smallest(l, r, cnt);
}
protected:
int length;
BitVector matrix[L];
int mid[L];
std::pair<int, int> succ(bool f, int l, int r, int level) const {
return {matrix[level].rank(f, l) + mid[level] * f, matrix[level].rank(f, r) + mid[level] * f};
}
};
} // namespace internal