cp-library

競技プログラミング用 C++ ライブラリ

View the Project on GitHub qandori/cp-library

:heavy_check_mark: 更新可能ビット列の区間個数(補助部品)

components/fenwick_bitset.hpp · GitHub で見る

共通ページ

FenwickBitset(n) は長さ n の全要素が false のビット列を作ります。set(p,value) で一点を代入し、contains(p) で値、count(l,r) で半開区間 [l,r) の true の個数を返します。size() は列長です。

構築・空間は \(O(n)\)、一点代入・区間個数は \(O(\log n)\)、値の取得は \(O(1)\) です。

依存ライブラリ

検証コード

コード

#ifndef FENWICK_BITSET_HPP
#define FENWICK_BITSET_HPP

#include "fenwick_sum.hpp"
#include <bit>
#include <cassert>
#include <cstdint>
#include <vector>

class FenwickBitset {
	std::vector<std::uint64_t> words;
	FenwickSum<int> counts;
	int n = 0;
  public:
	explicit FenwickBitset(int size = 0) : counts(size > 0 ? (std::size_t(size) + 63) / 64 : 0), n(size) {
		assert(size >= 0);
		words.resize((std::size_t(size) + 63) / 64 + 1);
	}
	int size() const { return n; }
	bool contains(int p) const {
		assert(0 <= p && p < n);
		return (words[p >> 6] >> (p & 63)) & 1;
	}
	void set(int p, bool value) {
		assert(0 <= p && p < n);
		std::uint64_t mask = std::uint64_t(1) << (p & 63);
		if (bool(words[p >> 6] & mask) == value) return;
		words[p >> 6] ^= mask;
		counts.add(p >> 6, value ? 1 : -1);
	}
	int count(int l, int r) const {
		assert(0 <= l && l <= r && r <= n);
		return counts.prod(l >> 6, r >> 6)
			+ std::popcount(words[r >> 6] & ((std::uint64_t(1) << (r & 63)) - 1))
			- std::popcount(words[l >> 6] & ((std::uint64_t(1) << (l & 63)) - 1));
	}
};

#endif
Back to top page