This documentation is automatically generated by online-judge-tools/verification-helper
#include "src/data-structure/FastSet.hpp"
整数の set を高速化したい時に使う
FastSet(ll n)
:長さ $n$ の bitset を作るvoid set(ll i)
:A[i] = true
を行うvoid reset(ll i)
:A[i] = false
を行うll next(ll i)
:$i$ を超える最小の要素を求める
A.upper_bound(i)
に相当A._Find_next(i)
に相当ll prev(ll i)
:$i$ より小さい最大の要素を求める
prev(A.lower_bound(i))
に相当時間計算量 $O(\log_{\text{word}} n)$ / クエリ
空間計算量 $(\frac{\text{word}}{\text{word} - 1}\cdot n + O(\log_{\text{word}} n))$ bits ($\boldsymbol{n}$ bits くらいのメモリを使います)
値域 $2^{30}$
$n = 2^{20}$ 回の 追加 + next クエリ | 所要時間 |
std::set | 467 ms |
std::bitset | 254 ms |
FastSet | 56 ms |
脅威の 8 倍速!
// using u64 = uint64_t;
const u64 B = 64;
struct FastSet {
u64 n;
vector<vector<u64>> a;
FastSet(u64 n_) : n(n_) {
do a.emplace_back(n_ = (n_ + B - 1) / B);
while(n_ > 1);
}
// bool operator[](ll i) const { return a[0][i / B] >> (i % B) & 1; }
void set(ll i) {
for(auto& v : a) {
v[i / B] |= 1ULL << (i % B);
i /= B;
}
}
void reset(ll i) {
for(auto& v : a) {
v[i / B] &= ~(1ULL << (i % B));
if(v[i / B]) break;
i /= B;
}
}
ll next(ll i) { // i を超える最⼩の要素
rep(h, 0, sz(a)) {
i++;
if(i / B >= sz(a[h])) break;
u64 d = a[h][i / B] >> (i % B);
if(d) {
i += countr_zero(d);
while(h--) i = i * B + countr_zero(a[h][i]);
return i;
}
i /= B;
}
return n;
}
ll prev(ll i) { // i より小さい最⼤の要素
rep(h, 0, sz(a)) {
i--;
if(i < 0) break;
u64 d = a[h][i / B] << (~i % B);
if(d) {
i -= countl_zero(d);
while(h--) i = i * B + __lg(a[h][i]);
return i;
}
i /= B;
}
return -1;
}
};
#line 1 "src/data-structure/FastSet.hpp"
// using u64 = uint64_t;
const u64 B = 64;
struct FastSet {
u64 n;
vector<vector<u64>> a;
FastSet(u64 n_) : n(n_) {
do a.emplace_back(n_ = (n_ + B - 1) / B);
while(n_ > 1);
}
// bool operator[](ll i) const { return a[0][i / B] >> (i % B) & 1; }
void set(ll i) {
for(auto& v : a) {
v[i / B] |= 1ULL << (i % B);
i /= B;
}
}
void reset(ll i) {
for(auto& v : a) {
v[i / B] &= ~(1ULL << (i % B));
if(v[i / B]) break;
i /= B;
}
}
ll next(ll i) { // i を超える最⼩の要素
rep(h, 0, sz(a)) {
i++;
if(i / B >= sz(a[h])) break;
u64 d = a[h][i / B] >> (i % B);
if(d) {
i += countr_zero(d);
while(h--) i = i * B + countr_zero(a[h][i]);
return i;
}
i /= B;
}
return n;
}
ll prev(ll i) { // i より小さい最⼤の要素
rep(h, 0, sz(a)) {
i--;
if(i < 0) break;
u64 d = a[h][i / B] << (~i % B);
if(d) {
i -= countl_zero(d);
while(h--) i = i * B + __lg(a[h][i]);
return i;
}
i /= B;
}
return -1;
}
};