diff --git a/data_structure/dynamic_bitset.hpp b/data_structure/dynamic_bitset.hpp new file mode 100644 index 00000000..655a24e4 --- /dev/null +++ b/data_structure/dynamic_bitset.hpp @@ -0,0 +1,335 @@ +#pragma once + +#include +#include +#include +#include +#include + +struct dynamic_bitset { + using ull = unsigned long long; + static constexpr int W = 64; + + int n = 0; // number of bits + int m = 0; // number of 64-bit blocks + std::vector a; // blocks + + dynamic_bitset() = default; + explicit dynamic_bitset(int n_, bool init_one = false) { reset_size(n_, init_one); } + explicit dynamic_bitset(const std::string &s) : dynamic_bitset(int(s.size())) { + const char *p = s.data(); + for (int blk = 0; blk < m; ++blk) { + int l = std::max(0, n - ((blk + 1) << 6)); + int r = n - (blk << 6); + ull x = 0; + for (int i = l; i < r; ++i) x = (x << 1) | ull(p[i] == '1'); + a[blk] = x; + } + } + + void reset_size(int n_, bool init_one = false) { + n = n_; + m = (n + W - 1) / W; + a.assign(m, init_one ? ~0ULL : 0ULL); + trim(); + } + + int size() const { return n; } + + // ---- low-level helpers ---- + ull last_mask() const { + int r = n & (W - 1); + if (r == 0) return ~0ULL; + return (r == 64 ? ~0ULL : ((1ULL << r) - 1ULL)); + } + void trim() { + if (m == 0) return; + a.back() &= last_mask(); + } + + static inline int ctz64(ull x) { return __builtin_ctzll(x); } + static inline int clz64(ull x) { return __builtin_clzll(x); } + static inline int msb_index64(ull x) { return 63 - clz64(x); } // x != 0 + void assert_index(int i) const { assert(0 <= i && i < n); } + void assert_same_size(const dynamic_bitset &o) const { assert(n == o.n); } + + // ---- basic bit ops ---- + bool test(int i) const { + assert_index(i); + return (a[i >> 6] >> (i & 63)) & 1ULL; + } + void set(int i) { + assert_index(i); + a[i >> 6] |= (1ULL << (i & 63)); + } + void reset(int i) { + assert_index(i); + a[i >> 6] &= ~(1ULL << (i & 63)); + } + void flip(int i) { + assert_index(i); + a[i >> 6] ^= (1ULL << (i & 63)); + } + void set(int i, bool v) { v ? set(i) : reset(i); } + + void reset_all() { std::fill(a.begin(), a.end(), 0ULL); } + void set_all() { + std::fill(a.begin(), a.end(), ~0ULL); + trim(); + } + void flip_all() { + for (auto &x : a) x = ~x; + trim(); + } + + // count (optional but handy) + int popcount() const { + int s = 0; + for (ull x : a) s += __builtin_popcountll(x); + return s; + } + int count() const { return popcount(); } + + // ---- bitwise ops ---- + // ---- any / none ---- + bool any() const { + for (ull x : a) + if (x) return true; + return false; + } + bool none() const { return !any(); } + + // ---- bitwise assign ops ---- + dynamic_bitset &operator^=(const dynamic_bitset &o) { + assert_same_size(o); + for (int i = 0; i < m; i++) a[i] ^= o.a[i]; + trim(); + return *this; + } + dynamic_bitset &operator|=(const dynamic_bitset &o) { + assert_same_size(o); + for (int i = 0; i < m; i++) a[i] |= o.a[i]; + trim(); + return *this; + } + dynamic_bitset &operator&=(const dynamic_bitset &o) { + assert_same_size(o); + for (int i = 0; i < m; i++) a[i] &= o.a[i]; + trim(); + return *this; + } + + friend dynamic_bitset operator^(dynamic_bitset l, const dynamic_bitset &r) { + l ^= r; + return l; + } + friend dynamic_bitset operator|(dynamic_bitset l, const dynamic_bitset &r) { + l |= r; + return l; + } + friend dynamic_bitset operator&(dynamic_bitset l, const dynamic_bitset &r) { + l &= r; + return l; + } + + bool operator==(const dynamic_bitset &o) const { return n == o.n && a == o.a; } + bool operator!=(const dynamic_bitset &o) const { return !(*this == o); } + int compare(const dynamic_bitset &o) const { + if (n != o.n) return n < o.n ? -1 : 1; + for (int i = m - 1; i >= 0; --i) { + if (a[i] != o.a[i]) return a[i] < o.a[i] ? -1 : 1; + } + return 0; + } + bool operator<(const dynamic_bitset &o) const { return compare(o) < 0; } + bool operator<=(const dynamic_bitset &o) const { return compare(o) <= 0; } + bool operator>(const dynamic_bitset &o) const { return compare(o) > 0; } + bool operator>=(const dynamic_bitset &o) const { return compare(o) >= 0; } + + // returns bitset b with b.test(i) == test(l + i) for 0 <= i < r - l + dynamic_bitset slice(int l, int r) const { + l = std::clamp(l, 0, n); + r = std::clamp(r, 0, n); + if (l >= r) return dynamic_bitset(); + + dynamic_bitset res(r - l); + int ws = l >> 6; + int bs = l & 63; + for (int i = 0; i < res.m; ++i) { + ull lo = (ws + i < m ? (a[ws + i] >> bs) : 0ULL); + ull hi = (bs && ws + i + 1 < m ? (a[ws + i + 1] << (W - bs)) : 0ULL); + res.a[i] = lo | hi; + } + res.trim(); + return res; + } + +private: + template static dynamic_bitset join_range(const Range &xs) { + int total = 0; + for (const auto &x : xs) total += x.n; + + dynamic_bitset res(total); + int cur = 0; + for (const auto &x : xs) { + int ws = cur >> 6; + int bs = cur & 63; + for (int i = 0; i < x.m; ++i) { + ull v = x.a[i]; + if (!v) continue; + res.a[ws + i] |= v << bs; + if (bs && ws + i + 1 < res.m) res.a[ws + i + 1] |= v >> (W - bs); + } + cur += x.n; + } + res.trim(); + return res; + } + +public: + static dynamic_bitset join(const std::vector &xs) { return join_range(xs); } + static dynamic_bitset join(std::initializer_list xs) { return join_range(xs); } + static dynamic_bitset join(const dynamic_bitset &a, const dynamic_bitset &b) { + return join({a, b}); + } + + dynamic_bitset operator~() const { + dynamic_bitset r = *this; + for (auto &x : r.a) x = ~x; + r.trim(); + return r; + } + + // ---- shifts ---- + dynamic_bitset &operator<<=(int k) { + if (k <= 0 || n == 0) return *this; + if (k >= n) { + reset_all(); + return *this; + } + int ws = k >> 6; + int bs = k & 63; + + if (ws) { + for (int i = m - 1; i >= 0; --i) { + ull v = (i - ws >= 0) ? a[i - ws] : 0ULL; + a[i] = v; + } + } + if (bs) { + for (int i = m - 1; i >= 0; --i) { + ull hi = a[i] << bs; + ull lo = (i ? (a[i - 1] >> (64 - bs)) : 0ULL); + a[i] = hi | lo; + } + } + // zero-fill lower words introduced by ws shift + if (ws) { + for (int i = 0; i < ws && i < m; ++i) a[i] = 0ULL; + } + trim(); + return *this; + } + + dynamic_bitset &operator>>=(int k) { + if (k <= 0 || n == 0) return *this; + if (k >= n) { + reset_all(); + return *this; + } + int ws = k >> 6; + int bs = k & 63; + + if (ws) { + for (int i = 0; i < m; ++i) { + ull v = (i + ws < m) ? a[i + ws] : 0ULL; + a[i] = v; + } + } + if (bs) { + for (int i = 0; i < m; ++i) { + ull lo = a[i] >> bs; + ull hi = (i + 1 < m ? (a[i + 1] << (64 - bs)) : 0ULL); + a[i] = lo | hi; + } + } + // zero-fill upper words introduced by ws shift + if (ws) { + for (int i = m - ws; i < m; ++i) + if (0 <= i && i < m) a[i] = 0ULL; + } + trim(); + return *this; + } + + friend dynamic_bitset operator<<(dynamic_bitset b, int k) { + b <<= k; + return b; + } + friend dynamic_bitset operator>>(dynamic_bitset b, int k) { + b >>= k; + return b; + } + + // ---- find set bits ---- + // returns smallest i with bit=1, or size() + int first() const { + for (int i = 0; i < m; ++i) { + ull x = a[i]; + if (x) return (i << 6) + ctz64(x); + } + return size(); + } + + // returns smallest j > i with bit=1, or size() + int next(int i) const { + if (n == 0) return size(); + int j = i + 1; + if (j <= 0) return first(); + if (j >= n) return size(); + + int b = j >> 6; + int off = j & 63; + + // mask out bits < off + ull x = a[b] & (~0ULL << off); + if (x) return (b << 6) + ctz64(x); + + for (int bb = b + 1; bb < m; ++bb) { + ull y = a[bb]; + if (y) return (bb << 6) + ctz64(y); + } + return size(); + } + + // returns largest i with bit=1, or -1 + int last() const { + for (int i = m - 1; i >= 0; --i) { + ull x = a[i]; + if (i == m - 1) x &= last_mask(); + if (x) return (i << 6) + msb_index64(x); + } + return -1; + } + + // returns largest j < i with bit=1, or -1 + int prev(int i) const { + if (n == 0) return -1; + int j = i - 1; + if (j < 0) return -1; + if (j >= n) return last(); + + int b = j >> 6; + int off = j & 63; + + ull mask = (off == 63) ? ~0ULL : ((1ULL << (off + 1)) - 1ULL); + ull x = a[b] & mask; + if (x) return (b << 6) + msb_index64(x); + + for (int bb = b - 1; bb >= 0; --bb) { + ull y = a[bb]; + if (y) return (bb << 6) + msb_index64(y); + } + return -1; + } +}; diff --git a/data_structure/dynamic_bitset.md b/data_structure/dynamic_bitset.md new file mode 100644 index 00000000..172833f7 --- /dev/null +++ b/data_structure/dynamic_bitset.md @@ -0,0 +1,92 @@ +--- +title: Dynamic Bitset (動的サイズ bitset) +documentation_of: ./dynamic_bitset.hpp +--- + +実行時にサイズを決定できる bitset.64 ビット整数のブロック列で表現し,ビット演算・シフト・集合探索を $O(n/64)$ で処理する.`std::bitset` はテンプレート引数でサイズをコンパイル時に固定する必要があるが,`dynamic_bitset` は `int n` を受け取って動的に確保する. + +## 使用方法 + +```cpp +dynamic_bitset bs(n); // n ビット,全 0 で初期化 +dynamic_bitset bs(n, true); // n ビット,全 1 で初期化 +dynamic_bitset bs("1010"); // 文字列から構築(最下位ビット = s[size-1]) +``` + +### 個別ビット操作 + +```cpp +bs.test(i); // i ビット目の値(bool) +bs.set(i); // i ビット目を 1 に +bs.reset(i); // i ビット目を 0 に +bs.flip(i); // i ビット目を反転 +bs.set(i, v); // i ビット目を v に設定 +``` + +### 全体操作 + +```cpp +bs.set_all(); // 全ビットを 1 に +bs.reset_all(); // 全ビットを 0 に +bs.flip_all(); // 全ビットを反転 +``` + +### ビット演算 + +```cpp +bs1 &= bs2; bs1 |= bs2; bs1 ^= bs2; // 代入形式 +bs1 & bs2; bs1 | bs2; bs1 ^ bs2; // コピー形式(同サイズが必要) +~bs; // 反転 +bs <<= k; bs >>= k; // シフト(k ビット左右) +bs << k; bs >> k; +``` + +### カウントと判定 + +```cpp +bs.popcount(); // (= bs.count())立っているビット数 +bs.any(); // 1 ビット以上立っているか +bs.none(); // 全ビットが 0 か +bs.size(); // ビット数 n +``` + +### 部分ビット列・連結 + +```cpp +// bs の [l, r) に対応する (r-l) ビットの bitset を返す +dynamic_bitset sub = bs.slice(l, r); + +// 複数の bitset を低ビット側から順に連結 +dynamic_bitset joined = dynamic_bitset::join(a, b); +dynamic_bitset joined = dynamic_bitset::join({a, b, c}); // 初期化リスト +dynamic_bitset joined = dynamic_bitset::join(vector_of_bitsets); // vector +``` + +### 立っているビットの探索 + +```cpp +bs.first(); // 最小の 1 ビットのインデックス(なければ size()) +bs.next(i); // i より大きい最小の 1 ビット(なければ size()) +bs.last(); // 最大の 1 ビットのインデックス(なければ -1) +bs.prev(i); // i より小さい最大の 1 ビット(なければ -1) +``` + +`first` / `next` を使った列挙例: + +```cpp +for (int i = bs.first(); i < bs.size(); i = bs.next(i)) { + // i は立っているビット +} +``` + +## 問題例 + +- [No.1444 !Andd - yukicoder](https://yukicoder.me/problems/no/1444) +- [No.1514 Squared Matching - yukicoder](https://yukicoder.me/problems/no/1514) +- [No.1560 majority x majority - yukicoder](https://yukicoder.me/problems/no/1560) +- [No.1782 ManyCoins - yukicoder](https://yukicoder.me/problems/no/1782) +- [No.1861 Required Number - yukicoder](https://yukicoder.me/problems/no/1861) +- [No.2319 Friends+ - yukicoder](https://yukicoder.me/problems/no/2319) +- [No.2542 Yokan for Two - yukicoder](https://yukicoder.me/problems/no/2542) +- [No.3041 非対称じゃんけん - yukicoder](https://yukicoder.me/problems/no/3041) +- [No.3060 Erase Binary Matrix - yukicoder](https://yukicoder.me/problems/no/3060) diff --git a/data_structure/test/dynamic_bitset.yuki1444.test.cpp b/data_structure/test/dynamic_bitset.yuki1444.test.cpp new file mode 100644 index 00000000..46d1bfd2 --- /dev/null +++ b/data_structure/test/dynamic_bitset.yuki1444.test.cpp @@ -0,0 +1,49 @@ +#define PROBLEM "https://yukicoder.me/problems/no/1444" +#include "../dynamic_bitset.hpp" +#include +#include +using namespace std; + +int main() { + cin.tie(nullptr), ios::sync_with_stdio(false); + + int N; + cin >> N; + vector A(N); + for (auto &x : A) cin >> x; + + int retu = 0; + dynamic_bitset bs(1 << 10), bsu(1 << 10); + bs.set(1); + + bool zero = false; + + for (int i = 0; i < N; ++i) { + if (A[i] == 0) { zero = true; } + + if (zero) { + cout << "1\n"; + continue; + } + dynamic_bitset bsnxt(1 << 10), bsunxt(1 << 10); + for (int s = 0; s < (1 << 10); ++s) + if (bs.test(s)) { + if (s * A[i] < (1 << 10)) + bsnxt.set(s * A[i]); + else { + retu++; + bsunxt.set(s * A[i] % (1 << 10)); + } + } + for (int s = 0; s < (1 << 10); ++s) { + if (bsu.test(s)) bsunxt.set(s * A[i] % (1 << 10)); + } + for (int s = 0; s < (1 << 10); ++s) { + if (bs.test(s) or bsu.test(s)) bsnxt.set(s & A[i]); + } + + bsu = bsunxt; + bs = bsnxt; + cout << bs.count() + retu << '\n'; + } +} diff --git a/data_structure/test/dynamic_bitset.yuki1514.test.cpp b/data_structure/test/dynamic_bitset.yuki1514.test.cpp new file mode 100644 index 00000000..228e84af --- /dev/null +++ b/data_structure/test/dynamic_bitset.yuki1514.test.cpp @@ -0,0 +1,24 @@ +#define PROBLEM "https://yukicoder.me/problems/no/1514" +#include "../dynamic_bitset.hpp" +#include +using namespace std; + +int main() { + cin.tie(nullptr), ios::sync_with_stdio(false); + + int N; + cin >> N; + long long ret = 0; + + dynamic_bitset used(N + 1); + + for (int x = 1; x <= N; ++x) { + if (used.test(x)) continue; + long long cnt = 0; + for (long long d = 1; x * d * d <= N; ++d) { + if (!used.test(x * d * d)) ++cnt, used.set(x * d * d); + } + ret += cnt * cnt; + } + cout << ret << '\n'; +} diff --git a/data_structure/test/dynamic_bitset.yuki1560.test.cpp b/data_structure/test/dynamic_bitset.yuki1560.test.cpp new file mode 100644 index 00000000..a6583fb3 --- /dev/null +++ b/data_structure/test/dynamic_bitset.yuki1560.test.cpp @@ -0,0 +1,45 @@ +#define PROBLEM "https://yukicoder.me/problems/no/1560" +#include "../dynamic_bitset.hpp" +#include +#include +#include +using namespace std; + +int main() { + cin.tie(nullptr), ios::sync_with_stdio(false); + + int N, M; + cin >> N >> M; + vector S(N, vector(M)); + for (auto &row : S) + for (auto &x : row) cin >> x; + + vector bs(M, dynamic_bitset(N)); + for (int i = 0; i < N; ++i) { + for (int j = 0; j < M; ++j) bs[j].set(i, S[i][j]); + } + + vector state(1 << M, dynamic_bitset(N)); + state.at(0).set_all(); + for (int j = 0; j < M; ++j) state[1 << j] = bs[j]; + + for (int s = 0; s < (1 << M); ++s) { + if (std::popcount((unsigned)s) <= 1) continue; + int i = 0; + while ((~s >> i) & 1) i++; + state[s] = state[1 << i] & state[s - (1 << i)]; + } + + vector dp(1 << M); + dp[0] = 1; + + for (int s = 0; s < (1 << M); ++s) { + int n = state[s].count(); + for (int j = 0; j < M; ++j) + if (~s & (1 << j)) { + int f = (state[s] & bs[j]).count(), a = n - f; + if (f >= a) dp[s | (1 << j)] += dp[s]; + } + } + cout << dp.back() << '\n'; +} diff --git a/data_structure/test/dynamic_bitset.yuki1782.test.cpp b/data_structure/test/dynamic_bitset.yuki1782.test.cpp new file mode 100644 index 00000000..f787b699 --- /dev/null +++ b/data_structure/test/dynamic_bitset.yuki1782.test.cpp @@ -0,0 +1,53 @@ +#define PROBLEM "https://yukicoder.me/problems/no/1782" +#include "../dynamic_bitset.hpp" +#include +#include +using namespace std; + +int main() { + cin.tie(nullptr), ios::sync_with_stdio(false); + + int N; + long long L; + cin >> N >> L; + vector W(N); + for (auto &x : W) cin >> x; + sort(W.begin(), W.end()); + dynamic_bitset bs(W.back() + 1); + long long ret = -1; + vector newcomer{0}; + int non = 0; + const int rec = W.back(); + for (long long lo = 0; lo <= L; lo += rec) { + vector next_comer; + while (!newcomer.empty()) { + int x = newcomer.back(); + newcomer.pop_back(); + if (bs.test(x)) continue; + bs.set(x); + ++non; + for (auto w : W) { + if (x + w >= rec) { + int d = x + w - rec; + if (!bs.test(d)) next_comer.push_back(d); + } else if (!bs.test(x + w)) { + newcomer.push_back(x + w); + } + } + } + newcomer = next_comer; + if (next_comer.empty()) { + long long dx = max(0LL, (L - lo) / rec - 10); + lo += dx * rec; + ret += dx * non; + } + ret += non; + if (lo + rec > L) { + for (int i = 0; i < rec; ++i) { + if (lo + i > L) ret -= bs.test(i); + } + break; + } + } + cout << ret << '\n'; +} diff --git a/data_structure/test/dynamic_bitset.yuki1861.test.cpp b/data_structure/test/dynamic_bitset.yuki1861.test.cpp new file mode 100644 index 00000000..c29dd078 --- /dev/null +++ b/data_structure/test/dynamic_bitset.yuki1861.test.cpp @@ -0,0 +1,51 @@ +#define PROBLEM "https://yukicoder.me/problems/no/1861" +#include "../dynamic_bitset.hpp" +#include +#include +using namespace std; + +std::vector> knapsack_first_fit(const std::vector &A, int K) { + dynamic_bitset bs(K + 1); + + bs.set(0); + std::vector> t2add(1, {0}); + + for (int a : A) { + auto diff = (bs << a) & ~bs; + t2add.push_back({}); + for (int j = diff.first(); j <= K; j = diff.next(j)) { + bs.set(j); + t2add.back().push_back(j); + } + } + return t2add; +} + +int main() { + cin.tie(nullptr), ios::sync_with_stdio(false); + + int N, K; + cin >> N >> K; + vector A(N); + for (auto &x : A) cin >> x; + + auto t2add = knapsack_first_fit(A, K); + + dynamic_bitset left(K + 1), right(K + 1); + for (const auto &is : t2add) + for (int i : is) left.set(i); + + if (!left.test(K)) { + puts("-1"); + } else { + int ret = 0; + right.set(K); + + for (int i = N - 1; i >= 0; --i) { + for (int j : t2add.at(i + 1)) left.reset(j); + if ((right & left).none()) ++ret; + right |= right >> A.at(i); + } + cout << ret << '\n'; + } +} diff --git a/data_structure/test/dynamic_bitset.yuki2319.test.cpp b/data_structure/test/dynamic_bitset.yuki2319.test.cpp new file mode 100644 index 00000000..46930b91 --- /dev/null +++ b/data_structure/test/dynamic_bitset.yuki2319.test.cpp @@ -0,0 +1,39 @@ +#define PROBLEM "https://yukicoder.me/problems/no/2319" +#include "../dynamic_bitset.hpp" +#include +#include +using namespace std; + +int main() { + cin.tie(nullptr), ios::sync_with_stdio(false); + int N, M; + cin >> N >> M; + vector is_friend(N, dynamic_bitset(N)), world_has(N, dynamic_bitset(N)); + vector P(N); + + for (int i = 0; i < N; ++i) cin >> P.at(i), P.at(i)--, world_has.at(P.at(i)).set(i); + + while (M--) { + int a, b; + cin >> a >> b; + --a, --b; + is_friend.at(a).set(b); + is_friend.at(b).set(a); + } + + int Q; + cin >> Q; + while (Q--) { + int x, y; + cin >> x >> y; + --x, --y; + if (P.at(x) != P.at(y) and (world_has.at(P.at(y)) & is_friend.at(x)).any()) { + puts("Yes"); + world_has.at(P.at(x)).reset(x); + P.at(x) = P.at(y); + world_has.at(P.at(x)).set(x); + } else { + puts("No"); + } + } +} diff --git a/data_structure/test/dynamic_bitset.yuki2542.test.cpp b/data_structure/test/dynamic_bitset.yuki2542.test.cpp new file mode 100644 index 00000000..a2822fdb --- /dev/null +++ b/data_structure/test/dynamic_bitset.yuki2542.test.cpp @@ -0,0 +1,30 @@ +#define PROBLEM "https://yukicoder.me/problems/no/2542" +#include "../dynamic_bitset.hpp" +#include +#include +#include +using namespace std; + +int main() { + cin.tie(nullptr), ios::sync_with_stdio(false); + int L, N; + cin >> L >> N; + vector X(N + 2); + for (int i = 1; i <= N; ++i) cin >> X[i]; + X[N + 1] = L; + + vector dp(2, vector(X.size(), dynamic_bitset(L + 1))); + dp.at(0).at(0).set(0); + for (int i = 0; i < (int)dp.at(0).size(); ++i) { + for (int j = i + 1; j < (int)dp.at(0).size(); ++j) { + const int w = X.at(j) - X.at(i); + for (int d = 0; d < 2; ++d) dp.at(d ^ 1).at(j) |= (dp.at(d).at(i) << (d ? w : 0)); + } + } + + int ret = L; + for (int i = 0; i <= L; ++i) { + if (dp.at(0).back().test(i)) ret = min(ret, abs(L - 2 * i)); + } + cout << ret << '\n'; +} diff --git a/data_structure/test/dynamic_bitset.yuki3041.test.cpp b/data_structure/test/dynamic_bitset.yuki3041.test.cpp new file mode 100644 index 00000000..8b3c1657 --- /dev/null +++ b/data_structure/test/dynamic_bitset.yuki3041.test.cpp @@ -0,0 +1,31 @@ +#define PROBLEM "https://yukicoder.me/problems/no/3041" +#include "../dynamic_bitset.hpp" +#include +#include +#include +using namespace std; + +int main() { + cin.tie(nullptr), ios::sync_with_stdio(false); + + int N, F; + cin >> N >> F; + vector A(N), B(N), C(N); + for (auto &a : A) cin >> a; + for (auto &b : B) cin >> b; + for (auto &c : C) cin >> c; + + dynamic_bitset bs(N * F + 1); + bs.set(0); + + for (int i = 0; i < N; ++i) { + int a = A.at(i), b = B.at(i), c = C.at(i); + if (a > b) swap(a, b); + if (b > c) swap(b, c); + if (a > b) swap(a, b); + b -= a; + c -= a; + bs = bs | (bs << b) | (bs << c); + cout << bs.count() << '\n'; + } +} diff --git a/data_structure/test/dynamic_bitset.yuki3060.test.cpp b/data_structure/test/dynamic_bitset.yuki3060.test.cpp new file mode 100644 index 00000000..9b4f80c0 --- /dev/null +++ b/data_structure/test/dynamic_bitset.yuki3060.test.cpp @@ -0,0 +1,32 @@ +#define PROBLEM "https://yukicoder.me/problems/no/3060" +#include "../dynamic_bitset.hpp" +#include +#include +#include +using namespace std; + +int main() { + cin.tie(nullptr), ios::sync_with_stdio(false); + + int H, W; + cin >> H >> W; + using BS = dynamic_bitset; + vector A(H); + for (int i = 0; i < H; ++i) { + string s; + cin >> s; + A.at(i) = BS(s); + } + + sort(A.begin(), A.end(), [&](const BS &l, const BS &r) { return l.count() < r.count(); }); + + vector dp(H + 1); + for (int i = 0; i < H; ++i) { + dp[i + 1] = max(dp[i + 1], 1); + for (int j = 0; j < i; ++j) { + if ((A.at(i) & A.at(j)) == A.at(j)) dp[i + 1] = max(dp[i + 1], dp[j + 1] + 1); + } + } + + cout << H - *max_element(dp.begin(), dp.end()) << '\n'; +}