a01sa01to's competitive programming library. Requires C++20 or higher with GCC. This documentation is automatically generated by online-judge-tools/verification-helper
#include "library/data-structure/dynamic-bitset.hpp"
Bitset の動的版。
基本的には (static な) bitset
と同じように扱える ([]
アクセスと to_ull()
以外)
DynamicBitset(n)
: $n$ ビットの Dynamic Bitset を生成。DynamicBitset(n, x)
: 数値 $x$ から $n$ ビットの Dynamic Bitset を生成。&=
|=
^=
<<=
>>=
~
==
!=
<<
>>
&
|
^
set()
: 全ビットを 1 にする。set(i, true)
: $i$ 番目のビットを 1 にする。set(i, false)
: $i$ 番目のビットを 0 にする。reset()
: 全ビットを 0 にする。reset(i)
: $i$ 番目のビットを 0 にする。flip()
: 全ビットを反転する。count()
: popcountsize()
: ビット数を返す。test(i)
: $i$ 番目のビットの値を返す。all()
: 全てのビットが 1 なら true を返す。any()
: 1 つでもビットが 1 なら true を返す。none()
: 全てのビットが 0 なら true を返す。to_ull()
: ビット列を unsigned long long に変換する。to_string()
: ビット列を文字列に変換する。#pragma once
#include <algorithm>
#include <bit>
#include <concepts>
#include <cstdint>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
using namespace std;
namespace asalib::ds {
class DynamicBitset {
private:
using ull = uint64_t;
size_t siz = 0;
// TODO: valarray が constexpr に対応したら変える
vector<ull> bits;
public:
constexpr explicit DynamicBitset() = default;
constexpr DynamicBitset(const DynamicBitset&) = default;
constexpr ~DynamicBitset() = default;
constexpr DynamicBitset& operator=(const DynamicBitset&) = default;
constexpr explicit DynamicBitset(const size_t size) {
siz = size;
bits.reserve((size + 63) >> 6);
bits.resize((size + 63) >> 6, 0);
}
template<integral T>
constexpr explicit DynamicBitset(const size_t size, const T value) {
// TODO: ほかの型も考慮する
static_assert(sizeof(T) <= sizeof(ull), "DynamicBitset: value type too large");
siz = size;
bits.reserve((size + 63) >> 6);
bits.resize((size + 63) >> 6, 0);
bits[0] = static_cast<ull>(value);
}
constexpr DynamicBitset& operator&=(const DynamicBitset& other) {
const size_t s = min(bits.size(), other.bits.size());
for (size_t i = 0; i < s; ++i) bits[i] &= other.bits[i];
return *this;
}
constexpr DynamicBitset& operator|=(const DynamicBitset& other) {
const size_t s = min(bits.size(), other.bits.size());
for (size_t i = 0; i < s; ++i) bits[i] |= other.bits[i];
return *this;
}
constexpr DynamicBitset& operator^=(const DynamicBitset& other) {
const size_t s = min(bits.size(), other.bits.size());
for (size_t i = 0; i < s; ++i) bits[i] ^= other.bits[i];
return *this;
}
constexpr DynamicBitset& operator<<=(const size_t shift) {
const size_t full = shift >> 6;
const size_t rem = shift & 63;
vector<ull> new_bits(bits.size(), 0);
for (size_t i = 0; i < bits.size(); ++i) {
if (i + full < new_bits.size()) {
new_bits[i + full] |= bits[i] << rem;
if (i + full + 1 < new_bits.size()) new_bits[i + full + 1] |= bits[i] >> (64 - rem);
}
}
bits = std::move(new_bits);
return *this;
}
constexpr DynamicBitset& operator>>=(const size_t shift) {
const size_t full = shift >> 6;
const size_t rem = shift & 63;
vector<ull> new_bits(bits.size(), 0);
for (size_t i = full; i < bits.size(); ++i) {
new_bits[i - full] |= bits[i] >> rem;
if (i - full - 1 < new_bits.size()) new_bits[i - full - 1] |= bits[i] << (64 - rem);
}
bits = std::move(new_bits);
return *this;
}
constexpr DynamicBitset& set() {
for (size_t i = 0; i < bits.size(); ++i) bits[i] = ~0ULL;
return *this;
}
constexpr DynamicBitset& set(const size_t pos, const bool val = true) {
if (pos >= siz) throw out_of_range("DynamicBitset::set: position out of range");
const size_t idx = pos >> 6;
const size_t bit = pos & 63;
if (val)
bits[idx] |= (1ULL << bit);
else
bits[idx] &= ~(1ULL << bit);
return *this;
}
constexpr DynamicBitset& reset() {
ranges::fill(bits, 0);
return *this;
}
constexpr DynamicBitset& reset(size_t pos) { return set(pos, false); }
constexpr DynamicBitset operator~() const {
DynamicBitset res = *this;
res.flip();
return res;
}
constexpr DynamicBitset& flip() {
for (size_t i = 0; i < bits.size(); ++i) bits[i] = ~bits[i];
return *this;
}
constexpr DynamicBitset& flip(const size_t pos) {
if (pos >= siz) throw out_of_range("DynamicBitset::flip: position out of range");
const size_t idx = pos >> 6;
const size_t bit = pos & 63;
bits[idx] ^= (1ULL << bit);
return *this;
}
constexpr size_t count() const {
size_t cnt = 0;
for (const ull& b : bits) cnt += popcount(b);
return cnt;
}
constexpr size_t size() const { return siz; }
constexpr bool test(const size_t pos) const {
if (pos >= siz) throw out_of_range("DynamicBitset::test: position out of range");
const size_t idx = pos >> 6;
const size_t bit = pos & 63;
return (bits[idx] >> bit) & 1;
}
constexpr bool all() const {
for (const ull& b : bits)
if (b != ~0ULL) return false;
return true;
}
constexpr bool any() const {
for (const ull& b : bits)
if (b != 0) return true;
return false;
}
constexpr bool none() const {
for (const ull& b : bits)
if (b != 0) return false;
return true;
}
constexpr ull to_ull() const {
if (bits.size() > 1) throw logic_error("DynamicBitset::to_ull: overflow");
if (bits.empty()) return 0;
return bits[0];
}
constexpr string to_string() const {
string res;
res.reserve(siz);
for (size_t i = 0; i < siz; ++i) res += (test(i) ? '1' : '0');
ranges::reverse(res);
return res;
}
constexpr bool operator==(const DynamicBitset& other) const {
if (siz != other.siz) return false;
for (size_t i = 0; i < bits.size(); ++i)
if (bits[i] != other.bits[i]) return false;
return true;
}
constexpr bool operator!=(const DynamicBitset& other) const {
return !(*this == other);
}
constexpr DynamicBitset operator<<(const size_t shift) const {
DynamicBitset res = *this;
res <<= shift;
return res;
}
constexpr DynamicBitset operator>>(const size_t shift) const {
DynamicBitset res = *this;
res >>= shift;
return res;
}
constexpr DynamicBitset operator&(const DynamicBitset& other) const {
DynamicBitset res = *this;
res &= other;
return res;
}
constexpr DynamicBitset operator|(const DynamicBitset& other) const {
DynamicBitset res = *this;
res |= other;
return res;
}
constexpr DynamicBitset operator^(const DynamicBitset& other) const {
DynamicBitset res = *this;
res ^= other;
return res;
}
};
} // namespace asalib::ds
#line 2 "library/data-structure/dynamic-bitset.hpp"
#include <algorithm>
#include <bit>
#include <concepts>
#include <cstdint>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
using namespace std;
namespace asalib::ds {
class DynamicBitset {
private:
using ull = uint64_t;
size_t siz = 0;
// TODO: valarray が constexpr に対応したら変える
vector<ull> bits;
public:
constexpr explicit DynamicBitset() = default;
constexpr DynamicBitset(const DynamicBitset&) = default;
constexpr ~DynamicBitset() = default;
constexpr DynamicBitset& operator=(const DynamicBitset&) = default;
constexpr explicit DynamicBitset(const size_t size) {
siz = size;
bits.reserve((size + 63) >> 6);
bits.resize((size + 63) >> 6, 0);
}
template<integral T>
constexpr explicit DynamicBitset(const size_t size, const T value) {
// TODO: ほかの型も考慮する
static_assert(sizeof(T) <= sizeof(ull), "DynamicBitset: value type too large");
siz = size;
bits.reserve((size + 63) >> 6);
bits.resize((size + 63) >> 6, 0);
bits[0] = static_cast<ull>(value);
}
constexpr DynamicBitset& operator&=(const DynamicBitset& other) {
const size_t s = min(bits.size(), other.bits.size());
for (size_t i = 0; i < s; ++i) bits[i] &= other.bits[i];
return *this;
}
constexpr DynamicBitset& operator|=(const DynamicBitset& other) {
const size_t s = min(bits.size(), other.bits.size());
for (size_t i = 0; i < s; ++i) bits[i] |= other.bits[i];
return *this;
}
constexpr DynamicBitset& operator^=(const DynamicBitset& other) {
const size_t s = min(bits.size(), other.bits.size());
for (size_t i = 0; i < s; ++i) bits[i] ^= other.bits[i];
return *this;
}
constexpr DynamicBitset& operator<<=(const size_t shift) {
const size_t full = shift >> 6;
const size_t rem = shift & 63;
vector<ull> new_bits(bits.size(), 0);
for (size_t i = 0; i < bits.size(); ++i) {
if (i + full < new_bits.size()) {
new_bits[i + full] |= bits[i] << rem;
if (i + full + 1 < new_bits.size()) new_bits[i + full + 1] |= bits[i] >> (64 - rem);
}
}
bits = std::move(new_bits);
return *this;
}
constexpr DynamicBitset& operator>>=(const size_t shift) {
const size_t full = shift >> 6;
const size_t rem = shift & 63;
vector<ull> new_bits(bits.size(), 0);
for (size_t i = full; i < bits.size(); ++i) {
new_bits[i - full] |= bits[i] >> rem;
if (i - full - 1 < new_bits.size()) new_bits[i - full - 1] |= bits[i] << (64 - rem);
}
bits = std::move(new_bits);
return *this;
}
constexpr DynamicBitset& set() {
for (size_t i = 0; i < bits.size(); ++i) bits[i] = ~0ULL;
return *this;
}
constexpr DynamicBitset& set(const size_t pos, const bool val = true) {
if (pos >= siz) throw out_of_range("DynamicBitset::set: position out of range");
const size_t idx = pos >> 6;
const size_t bit = pos & 63;
if (val)
bits[idx] |= (1ULL << bit);
else
bits[idx] &= ~(1ULL << bit);
return *this;
}
constexpr DynamicBitset& reset() {
ranges::fill(bits, 0);
return *this;
}
constexpr DynamicBitset& reset(size_t pos) { return set(pos, false); }
constexpr DynamicBitset operator~() const {
DynamicBitset res = *this;
res.flip();
return res;
}
constexpr DynamicBitset& flip() {
for (size_t i = 0; i < bits.size(); ++i) bits[i] = ~bits[i];
return *this;
}
constexpr DynamicBitset& flip(const size_t pos) {
if (pos >= siz) throw out_of_range("DynamicBitset::flip: position out of range");
const size_t idx = pos >> 6;
const size_t bit = pos & 63;
bits[idx] ^= (1ULL << bit);
return *this;
}
constexpr size_t count() const {
size_t cnt = 0;
for (const ull& b : bits) cnt += popcount(b);
return cnt;
}
constexpr size_t size() const { return siz; }
constexpr bool test(const size_t pos) const {
if (pos >= siz) throw out_of_range("DynamicBitset::test: position out of range");
const size_t idx = pos >> 6;
const size_t bit = pos & 63;
return (bits[idx] >> bit) & 1;
}
constexpr bool all() const {
for (const ull& b : bits)
if (b != ~0ULL) return false;
return true;
}
constexpr bool any() const {
for (const ull& b : bits)
if (b != 0) return true;
return false;
}
constexpr bool none() const {
for (const ull& b : bits)
if (b != 0) return false;
return true;
}
constexpr ull to_ull() const {
if (bits.size() > 1) throw logic_error("DynamicBitset::to_ull: overflow");
if (bits.empty()) return 0;
return bits[0];
}
constexpr string to_string() const {
string res;
res.reserve(siz);
for (size_t i = 0; i < siz; ++i) res += (test(i) ? '1' : '0');
ranges::reverse(res);
return res;
}
constexpr bool operator==(const DynamicBitset& other) const {
if (siz != other.siz) return false;
for (size_t i = 0; i < bits.size(); ++i)
if (bits[i] != other.bits[i]) return false;
return true;
}
constexpr bool operator!=(const DynamicBitset& other) const {
return !(*this == other);
}
constexpr DynamicBitset operator<<(const size_t shift) const {
DynamicBitset res = *this;
res <<= shift;
return res;
}
constexpr DynamicBitset operator>>(const size_t shift) const {
DynamicBitset res = *this;
res >>= shift;
return res;
}
constexpr DynamicBitset operator&(const DynamicBitset& other) const {
DynamicBitset res = *this;
res &= other;
return res;
}
constexpr DynamicBitset operator|(const DynamicBitset& other) const {
DynamicBitset res = *this;
res |= other;
return res;
}
constexpr DynamicBitset operator^(const DynamicBitset& other) const {
DynamicBitset res = *this;
res ^= other;
return res;
}
};
} // namespace asalib::ds