kyopro-lib

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

View on GitHub

:warning: Range mode query
(Mylib/Typical/range_mode_query.cpp)

Operations

Requirements

Notes

Problems

References

Code

#pragma once
#include <algorithm>
#include <cmath>
#include <utility>
#include <vector>

namespace haar_lib {
  template <typename T>
  class range_mode_query {
    std::vector<T> a_, D_;
    std::vector<int> b_, b_index_;
    int N_, block_size_, block_num_, K_;
    std::vector<std::vector<int>> index_, mode_, freq_;

  public:
    range_mode_query() {}
    range_mode_query(std::vector<T> a) : a_(a), D_(a), N_(a.size()), block_size_(std::sqrt(N_)), block_num_((N_ + block_size_ - 1) / block_size_), mode_(block_num_, std::vector<int>(block_num_)), freq_(block_num_, std::vector<int>(block_num_)) {
      std::sort(D_.begin(), D_.end());
      D_.erase(std::unique(D_.begin(), D_.end()), D_.end());

      b_.resize(N_);
      for (int i = 0; i < N_; ++i) {
        b_[i] = std::lower_bound(D_.begin(), D_.end(), a_[i]) - D_.begin();
      }

      K_ = D_.size();

      index_.resize(K_);
      b_index_.resize(N_);
      for (int i = 0; i < N_; ++i) {
        b_index_[i] = index_[b_[i]].size();
        index_[b_[i]].push_back(i);
      }

      for (int i = 0; i < block_num_; ++i) {
        std::vector<int> temp(K_);
        int md = 0, fr = 0;

        for (int j = i; j < block_num_; ++j) {
          int R = std::min(N_, block_size_ * (j + 1));
          for (int x = block_size_ * j; x < R; ++x) {
            temp[b_[x]] += 1;

            if (temp[b_[x]] > fr) {
              md = b_[x];
              fr = temp[b_[x]];
            }
          }

          mode_[i][j] = md;
          freq_[i][j] = fr;
        }
      }
    }

    std::pair<int, T> query(int l, int r) {  // [l, r)
      std::pair<int, T> ret = std::make_pair(0, 0);

      const int span_l = (l + block_size_ - 1) / block_size_, span_r = r / block_size_ - 1;

      if (span_l <= span_r) {
        ret = std::make_pair(freq_[span_l][span_r], D_[mode_[span_l][span_r]]);
      }

      // prefix
      for (int i = l; i < std::min(r, span_l * block_size_); ++i) {
        if (b_index_[i] - 1 >= 0 and index_[b_[i]][b_index_[i] - 1] >= l) continue;

        if (b_index_[i] + ret.first - 1 < 0 or
            (b_index_[i] + ret.first - 1 < (int) index_[b_[i]].size() and index_[b_[i]][b_index_[i] + ret.first - 1] < r)) {
          int fr = ret.first;

          for (int j = b_index_[i] + ret.first; j < (int) index_[b_[i]].size(); ++j) {
            if (index_[b_[i]][j] < r)
              ++fr;
            else
              break;
          }

          if (fr > ret.first) {
            ret = std::make_pair(fr, D_[b_[i]]);
          }
        }
      }

      // suffix
      for (int i = r - 1; i >= std::max(l, (span_r + 1) * block_size_); --i) {
        if (b_index_[i] + 1 < (int) index_[b_[i]].size() and index_[b_[i]][b_index_[i] + 1] < r) continue;

        if (b_index_[i] - ret.first + 1 >= (int) index_[b_[i]].size() or
            (b_index_[i] - ret.first + 1 >= 0 and index_[b_[i]][b_index_[i] - ret.first + 1] >= l)) {
          int fr = ret.first;

          for (int j = b_index_[i] - ret.first; j >= 0; --j) {
            if (index_[b_[i]][j] >= l)
              ++fr;
            else
              break;
          }

          if (fr > ret.first) {
            ret = std::make_pair(fr, D_[b_[i]]);
          }
        }
      }

      return ret;
    }
  };
}  // namespace haar_lib
#line 2 "Mylib/Typical/range_mode_query.cpp"
#include <algorithm>
#include <cmath>
#include <utility>
#include <vector>

namespace haar_lib {
  template <typename T>
  class range_mode_query {
    std::vector<T> a_, D_;
    std::vector<int> b_, b_index_;
    int N_, block_size_, block_num_, K_;
    std::vector<std::vector<int>> index_, mode_, freq_;

  public:
    range_mode_query() {}
    range_mode_query(std::vector<T> a) : a_(a), D_(a), N_(a.size()), block_size_(std::sqrt(N_)), block_num_((N_ + block_size_ - 1) / block_size_), mode_(block_num_, std::vector<int>(block_num_)), freq_(block_num_, std::vector<int>(block_num_)) {
      std::sort(D_.begin(), D_.end());
      D_.erase(std::unique(D_.begin(), D_.end()), D_.end());

      b_.resize(N_);
      for (int i = 0; i < N_; ++i) {
        b_[i] = std::lower_bound(D_.begin(), D_.end(), a_[i]) - D_.begin();
      }

      K_ = D_.size();

      index_.resize(K_);
      b_index_.resize(N_);
      for (int i = 0; i < N_; ++i) {
        b_index_[i] = index_[b_[i]].size();
        index_[b_[i]].push_back(i);
      }

      for (int i = 0; i < block_num_; ++i) {
        std::vector<int> temp(K_);
        int md = 0, fr = 0;

        for (int j = i; j < block_num_; ++j) {
          int R = std::min(N_, block_size_ * (j + 1));
          for (int x = block_size_ * j; x < R; ++x) {
            temp[b_[x]] += 1;

            if (temp[b_[x]] > fr) {
              md = b_[x];
              fr = temp[b_[x]];
            }
          }

          mode_[i][j] = md;
          freq_[i][j] = fr;
        }
      }
    }

    std::pair<int, T> query(int l, int r) {  // [l, r)
      std::pair<int, T> ret = std::make_pair(0, 0);

      const int span_l = (l + block_size_ - 1) / block_size_, span_r = r / block_size_ - 1;

      if (span_l <= span_r) {
        ret = std::make_pair(freq_[span_l][span_r], D_[mode_[span_l][span_r]]);
      }

      // prefix
      for (int i = l; i < std::min(r, span_l * block_size_); ++i) {
        if (b_index_[i] - 1 >= 0 and index_[b_[i]][b_index_[i] - 1] >= l) continue;

        if (b_index_[i] + ret.first - 1 < 0 or
            (b_index_[i] + ret.first - 1 < (int) index_[b_[i]].size() and index_[b_[i]][b_index_[i] + ret.first - 1] < r)) {
          int fr = ret.first;

          for (int j = b_index_[i] + ret.first; j < (int) index_[b_[i]].size(); ++j) {
            if (index_[b_[i]][j] < r)
              ++fr;
            else
              break;
          }

          if (fr > ret.first) {
            ret = std::make_pair(fr, D_[b_[i]]);
          }
        }
      }

      // suffix
      for (int i = r - 1; i >= std::max(l, (span_r + 1) * block_size_); --i) {
        if (b_index_[i] + 1 < (int) index_[b_[i]].size() and index_[b_[i]][b_index_[i] + 1] < r) continue;

        if (b_index_[i] - ret.first + 1 >= (int) index_[b_[i]].size() or
            (b_index_[i] - ret.first + 1 >= 0 and index_[b_[i]][b_index_[i] - ret.first + 1] >= l)) {
          int fr = ret.first;

          for (int j = b_index_[i] - ret.first; j >= 0; --j) {
            if (index_[b_[i]][j] >= l)
              ++fr;
            else
              break;
          }

          if (fr > ret.first) {
            ret = std::make_pair(fr, D_[b_[i]]);
          }
        }
      }

      return ret;
    }
  };
}  // namespace haar_lib
Back to top page