164 lines
5.1 KiB
C++
164 lines
5.1 KiB
C++
#include <algorithm>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <iostream>
|
|
#include <vector>
|
|
|
|
struct dynamic_bitset {
|
|
int len = 0;
|
|
typedef unsigned long long ULL;
|
|
std::vector<ULL> val;
|
|
dynamic_bitset() noexcept = default;
|
|
|
|
~dynamic_bitset() noexcept = default;
|
|
|
|
dynamic_bitset(const dynamic_bitset &) noexcept = default;
|
|
|
|
dynamic_bitset &operator=(const dynamic_bitset &) noexcept = default;
|
|
|
|
dynamic_bitset(std::size_t n) noexcept {
|
|
len = n;
|
|
val.resize((n + 63) / 64);
|
|
for (int i = (n + 63) / 64 - 1; i >= 0; i--) val[i] = 0;
|
|
}
|
|
|
|
dynamic_bitset(const std::string &str) noexcept {
|
|
len = str.size();
|
|
val.resize((len + 63) / 64);
|
|
for (int i = 0; i < val.size(); i++) val[i] = 0;
|
|
for (int i = 0; i < len; i++)
|
|
val[i / 64] |= ((1ull * (str[i] - '0')) << (i % 64));
|
|
}
|
|
|
|
inline bool operator[](std::size_t n) const noexcept {
|
|
return (val[n / 64] & (1ull << (n % 64))) != 0;
|
|
}
|
|
|
|
dynamic_bitset &set(std::size_t n, bool __val = true) noexcept {
|
|
val[n / 64] &= ULL(-1) ^ (1ull << (n % 64));
|
|
val[n / 64] |= ((1ull * __val) << (n % 64));
|
|
return *this;
|
|
}
|
|
|
|
dynamic_bitset &push_back(bool __val) noexcept {
|
|
len++;
|
|
if (len % 64 == 1)
|
|
val.push_back((ULL)__val);
|
|
else
|
|
val[(len - 1) / 64] |= ((1ull * __val) << ((len - 1) % 64));
|
|
return *this;
|
|
}
|
|
|
|
bool none() const noexcept {
|
|
for (int i = 0; i < val.size(); i++)
|
|
if (val[i] != 0) return false;
|
|
return true;
|
|
}
|
|
|
|
bool all() const noexcept {
|
|
for (int i = 0; i < val.size() - 1; i++)
|
|
if (val[i] != ULL(-1)) return false;
|
|
if (val[val.size() - 1] !=
|
|
ULL((1ull << (len % 64 == 0 ? 64 : len % 64)) - 1))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
inline std::size_t size() const noexcept { return len; }
|
|
|
|
dynamic_bitset &operator|=(const dynamic_bitset &B) noexcept {
|
|
int op_len = std::min(len, B.len);
|
|
int op_buckets = (op_len + 63) / 64;
|
|
for (int i = 0; i < op_buckets - 1; i++) val[i] |= B.val[i];
|
|
val[op_buckets - 1] |=
|
|
(ULL((1ull << (op_len % 64 == 0 ? 64 : op_len % 64)) - 1ll)) &
|
|
B.val[op_buckets - 1];
|
|
return *this;
|
|
}
|
|
|
|
dynamic_bitset &operator&=(const dynamic_bitset &B) noexcept {
|
|
int op_len = std::min(len, B.len);
|
|
int op_buckets = (op_len + 63) / 64;
|
|
for (int i = 0; i < op_buckets - 1; i++) val[i] &= B.val[i];
|
|
val[op_buckets - 1] &=
|
|
(~ULL((1ull << (op_len % 64 == 0 ? 64 : op_len % 64)) - 1ll)) |
|
|
B.val[op_buckets - 1];
|
|
return *this;
|
|
}
|
|
|
|
dynamic_bitset &operator^=(const dynamic_bitset &B) noexcept {
|
|
int op_len = std::min(len, B.len);
|
|
int op_buckets = (op_len + 63) / 64;
|
|
for (int i = 0; i < op_buckets - 1; i++) val[i] ^= B.val[i];
|
|
val[op_buckets - 1] ^=
|
|
(ULL((1ull << (op_len % 64 == 0 ? 64 : op_len % 64)) - 1ll)) &
|
|
B.val[op_buckets - 1];
|
|
return *this;
|
|
}
|
|
|
|
dynamic_bitset &operator<<=(std::size_t n) noexcept {
|
|
int big_move = n / 64, small_move = n % 64;
|
|
int ors = val.size();
|
|
val.resize((n + len + 63) / 64);
|
|
int obn = val.size();
|
|
if (small_move == 0) {
|
|
std::memmove(val.data() + big_move, val.data(), sizeof(ULL) * ors);
|
|
std::memset(val.data(), 0, sizeof(ULL) * std::min(big_move, ors));
|
|
} else {
|
|
for (int i = (n + len + 63) / 64 - 1; i >= big_move; i--) {
|
|
val[i] = (((i - big_move >= 0 && i - big_move < obn ? val[i - big_move]
|
|
: 0) &
|
|
ULL(((1ull << (64 - small_move))) - 1))
|
|
<< small_move) |
|
|
((i - big_move - 1 >= 0 ? val[i - big_move - 1] : 0) >>
|
|
(64 - small_move));
|
|
}
|
|
std::memset(val.data(), 0, sizeof(ULL) * std::min(big_move, ors));
|
|
}
|
|
len += n;
|
|
return *this;
|
|
}
|
|
|
|
dynamic_bitset &operator>>=(std::size_t n) noexcept {
|
|
if (n > len) n = len;
|
|
int big_move = n / 64, small_move = n % 64;
|
|
int obn = val.size();
|
|
if (small_move == 0) {
|
|
for (int i = 0; i < (len - n + 63) / 64; i++) {
|
|
val[i] = (i + big_move < obn ? val[i + big_move] : 0);
|
|
}
|
|
} else {
|
|
for (int i = 0; i < (len - n + 63) / 64; i++) {
|
|
val[i] = ((i + big_move < obn ? val[i + big_move] : 0) >> small_move) |
|
|
((i + big_move + 1 < obn ? val[i + big_move + 1] : 0)
|
|
<< (64 - small_move));
|
|
}
|
|
}
|
|
len -= n;
|
|
val.resize((len + 63) / 64);
|
|
if (val.size() > 0)
|
|
val[val.size() - 1] &=
|
|
ULL((1ull << (len % 64 == 0 ? 64 : len % 64)) - 1ll);
|
|
return *this;
|
|
}
|
|
|
|
dynamic_bitset &set() noexcept {
|
|
if (len == 0) return *this;
|
|
std::memset(val.data(), -1, sizeof(ULL) * val.size());
|
|
val[val.size() - 1] = ULL((1ull << (len % 64 == 0 ? 64 : len % 64)) - 1ll);
|
|
return *this;
|
|
}
|
|
|
|
dynamic_bitset &flip() noexcept {
|
|
if (len == 0) return *this;
|
|
for (int i = 0; i < val.size() - 1; i++) val[i] = ~val[i];
|
|
val[val.size() - 1] ^= ULL((1ull << (len % 64 == 0 ? 64 : len % 64)) - 1ll);
|
|
return *this;
|
|
}
|
|
|
|
dynamic_bitset &reset() noexcept {
|
|
if (len == 0) return *this;
|
|
std::memset(val.data(), 0, sizeof(ULL) * val.size());
|
|
return *this;
|
|
}
|
|
}; |