kyopro-lib

This documentation is automatically generated by online-judge-tools/verification-helper

View on GitHub

:question: Succinct dictionary
(Mylib/DataStructure/WaveletMatrix/succinct_dictionary.cpp)

Operations

Requirements

Notes

Problems

References

Required by

Verified with

Code

#pragma once
#include <cassert>
#include <optional>
#include <vector>

namespace haar_lib {
  class succinct_dict {
    int N_;

    static const int chunk_size_ = 256;
    static const int block_size_ = 64;
    std::vector<uint64_t> data_;

    std::vector<std::vector<uint8_t>> blocks_;

    std::vector<uint32_t> chunks_;

    int chunk_num_;
    static const int block_num_ = chunk_size_ / block_size_;

  public:
    succinct_dict() : N_(0) {}
    succinct_dict(const std::vector<bool> &b) : N_(b.size()) {
      chunk_num_ = (N_ + chunk_size_ - 1) / chunk_size_;

      data_.assign(chunk_num_ * block_num_ + 1, 0);

      for (int i = 0; i < N_; ++i) {
        if (b[i]) {
          int block_index = i / block_size_;
          int index       = i % block_size_;
          data_[block_index] |= (1LL << index);
        }
      }

      chunks_.assign(chunk_num_ + 1, 0);
      blocks_.assign(chunk_num_ + 1, std::vector<uint8_t>(block_num_, 0));

      for (int i = 0; i < chunk_num_; ++i) {
        for (int j = 0; j < block_num_ - 1; ++j) {
          blocks_[i][j + 1] = blocks_[i][j] + __builtin_popcountll(data_[i * block_num_ + j]);
        }

        chunks_[i + 1] = chunks_[i] + blocks_[i][block_num_ - 1] + __builtin_popcountll(data_[(i + 1) * block_num_ - 1]);
      }
    }

    int size() const { return N_; }

    /**
     * @return [0, index)のbの個数
     */
    int rank(int index, int b) const {
      if (b == 0) {
        return index - rank(index, 1);
      } else {
        if (index > N_) index = N_;

        const int chunk_pos = index / chunk_size_;
        const int block_pos = (index % chunk_size_) / block_size_;

        const uint64_t mask =
            data_[chunk_pos * block_num_ + block_pos] & ((1LL << (index % block_size_)) - 1);

        const int ret = chunks_[chunk_pos] +
                        blocks_[chunk_pos][block_pos] +
                        __builtin_popcountll(mask);

        return ret;
      }
    }

    /**
     * @return [l, r)のbの個数
     */
    int count(int l, int r, int b) const {
      return rank(r, b) - rank(l, b);
    }

    /**
     * @return b[index]
     */
    int access(int index) const {
      return (data_[index / block_size_] >> (index % block_size_)) & 1;
    }

    /**
     * @note n in [1, N]
     * @return 先頭からn番目のbの位置
     */
    std::optional<int> select(int n, int b) const {
      assert(n >= 1);

      if (rank(N_, b) < n) return {};

      int lb = -1, ub = N_;
      while (std::abs(lb - ub) > 1) {
        int mid = (lb + ub) / 2;

        if (rank(mid, b) >= n) {
          ub = mid;
        } else {
          lb = mid;
        }
      }

      return {lb};
    }
  };
}  // namespace haar_lib
#line 2 "Mylib/DataStructure/WaveletMatrix/succinct_dictionary.cpp"
#include <cassert>
#include <optional>
#include <vector>

namespace haar_lib {
  class succinct_dict {
    int N_;

    static const int chunk_size_ = 256;
    static const int block_size_ = 64;
    std::vector<uint64_t> data_;

    std::vector<std::vector<uint8_t>> blocks_;

    std::vector<uint32_t> chunks_;

    int chunk_num_;
    static const int block_num_ = chunk_size_ / block_size_;

  public:
    succinct_dict() : N_(0) {}
    succinct_dict(const std::vector<bool> &b) : N_(b.size()) {
      chunk_num_ = (N_ + chunk_size_ - 1) / chunk_size_;

      data_.assign(chunk_num_ * block_num_ + 1, 0);

      for (int i = 0; i < N_; ++i) {
        if (b[i]) {
          int block_index = i / block_size_;
          int index       = i % block_size_;
          data_[block_index] |= (1LL << index);
        }
      }

      chunks_.assign(chunk_num_ + 1, 0);
      blocks_.assign(chunk_num_ + 1, std::vector<uint8_t>(block_num_, 0));

      for (int i = 0; i < chunk_num_; ++i) {
        for (int j = 0; j < block_num_ - 1; ++j) {
          blocks_[i][j + 1] = blocks_[i][j] + __builtin_popcountll(data_[i * block_num_ + j]);
        }

        chunks_[i + 1] = chunks_[i] + blocks_[i][block_num_ - 1] + __builtin_popcountll(data_[(i + 1) * block_num_ - 1]);
      }
    }

    int size() const { return N_; }

    /**
     * @return [0, index)のbの個数
     */
    int rank(int index, int b) const {
      if (b == 0) {
        return index - rank(index, 1);
      } else {
        if (index > N_) index = N_;

        const int chunk_pos = index / chunk_size_;
        const int block_pos = (index % chunk_size_) / block_size_;

        const uint64_t mask =
            data_[chunk_pos * block_num_ + block_pos] & ((1LL << (index % block_size_)) - 1);

        const int ret = chunks_[chunk_pos] +
                        blocks_[chunk_pos][block_pos] +
                        __builtin_popcountll(mask);

        return ret;
      }
    }

    /**
     * @return [l, r)のbの個数
     */
    int count(int l, int r, int b) const {
      return rank(r, b) - rank(l, b);
    }

    /**
     * @return b[index]
     */
    int access(int index) const {
      return (data_[index / block_size_] >> (index % block_size_)) & 1;
    }

    /**
     * @note n in [1, N]
     * @return 先頭からn番目のbの位置
     */
    std::optional<int> select(int n, int b) const {
      assert(n >= 1);

      if (rank(N_, b) < n) return {};

      int lb = -1, ub = N_;
      while (std::abs(lb - ub) > 1) {
        int mid = (lb + ub) / 2;

        if (rank(mid, b) >= n) {
          ub = mid;
        } else {
          lb = mid;
        }
      }

      return {lb};
    }
  };
}  // namespace haar_lib
Back to top page