cp-library

C++ Library for Competitive Programming

View the Project on GitHub emthrm/cp-library

:heavy_check_mark: その他/平方分割
(test/misc/sqrt_decomposition.test.cpp)

Depends on

Code

/*
 * @title その他/平方分割
 *
 * verification-helper: PROBLEM http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_G
 */

#include <iostream>
#include <vector>

#include "emthrm/misc/sqrt_decomposition.hpp"

std::vector<long long> a, b, lazy;

template <typename T>
void emthrm::SqrtDecomposition::partial_update(const int idx, const T val) {
  a[idx] += val;
  b[idx / block_size] += val;
}

template <typename T>
void emthrm::SqrtDecomposition::total_update(const int idx, const T val) {
  lazy[idx] += val;
  to_be_eval[idx] = true;
}

template <typename T>
void emthrm::SqrtDecomposition::partial_query(const int idx, T* val) {
  const int block = idx / block_size;
  if (to_be_eval[block]) {
    for (int i = ls[block]; i < rs[block]; ++i) {
      partial_update(i, lazy[block]);
    }
    lazy[block] = 0;
    to_be_eval[block] = false;
  }
  *val += a[idx];
}

template <typename T>
void emthrm::SqrtDecomposition::total_query(const int idx, T* val) {
  *val += b[idx] + lazy[idx] * (rs[idx] - ls[idx]);
}

int main() {
  int n, q;
  std::cin >> n >> q;
  emthrm::SqrtDecomposition sqrt_decomposition(n);
  a.assign(n, 0);
  b.assign(sqrt_decomposition.n, 0);
  lazy.assign(sqrt_decomposition.n, 0);
  while (q--) {
    int type, s, t;
    std::cin >> type >> s >> t;
    --s; --t;
    if (type == 0) {
      int x;
      std::cin >> x;
      sqrt_decomposition.update(s, t + 1, x);
    } else if (type == 1) {
      std::cout << sqrt_decomposition.query(s, t + 1, 0LL) << '\n';
    }
  }
  return 0;
}
#line 1 "test/misc/sqrt_decomposition.test.cpp"
/*
 * @title その他/平方分割
 *
 * verification-helper: PROBLEM http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_G
 */

#include <iostream>
#include <vector>

#line 1 "include/emthrm/misc/sqrt_decomposition.hpp"



#include <cmath>
#line 6 "include/emthrm/misc/sqrt_decomposition.hpp"

namespace emthrm {

struct SqrtDecomposition {
  const int block_size, n;
  std::vector<int> ls, rs;
  std::vector<bool> to_be_eval;

  explicit SqrtDecomposition(const int n_)
      : block_size(std::round(std::sqrt(n_))),
        n((n_ + block_size - 1) / block_size) {
    ls.resize(n);
    rs.resize(n);
    to_be_eval.assign(n, false);
    for (int i = 0; i < n; ++i) {
      ls[i] = block_size * i;
      rs[i] = (i + 1 == n ? n_ : block_size * (i + 1));
    }
  }

  template <typename T> void partial_update(const int idx, const T val);

  template <typename T> void total_update(const int idx, const T val);

  template <typename T>
  void update(const int l, const int r, const T val) {
    if (r <= l) [[unlikely]] return;
    const int b_l = l / block_size, b_r = (r - 1) / block_size;
    if (b_l < b_r) {
      if (l == ls[b_l]) {
        total_update(b_l, val);
      } else {
        for (int i = l; i < rs[b_l]; ++i) {
          partial_update(i, val);
        }
      }
      for (int i = b_l + 1; i < b_r; ++i) {
        total_update(i, val);
      }
      if (r == rs[b_r]) {
        total_update(b_r, val);
      } else {
        for (int i = ls[b_r]; i < r; ++i) {
          partial_update(i, val);
        }
      }
    } else {
      for (int i = l; i < r; ++i) {
        partial_update(i, val);
      }
    }
  }

  template <typename T> void partial_query(const int idx, T* val);

  template <typename T> void total_query(const int idx, T* val);

  template <typename T>
  T query(const int l, const int r, const T id) {
    const int b_l = l / block_size, b_r = (r - 1) / block_size;
    T res = id;
    if (b_l < b_r) {
      if (l == ls[b_l]) {
        total_query(b_l, &res);
      } else {
        for (int i = l; i < rs[b_l]; ++i) {
          partial_query(i, &res);
        }
      }
      for (int i = b_l + 1; i < b_r; ++i) {
        total_query(i, &res);
      }
      if (r == rs[b_r]) {
        total_query(b_r, &res);
      } else {
        for (int i = ls[b_r]; i < r; ++i) {
          partial_query(i, &res);
        }
      }
    } else {
      for (int i = l; i < r; ++i) {
        partial_query(i, &res);
      }
    }
    return res;
  }
};

}  // namespace emthrm


#line 11 "test/misc/sqrt_decomposition.test.cpp"

std::vector<long long> a, b, lazy;

template <typename T>
void emthrm::SqrtDecomposition::partial_update(const int idx, const T val) {
  a[idx] += val;
  b[idx / block_size] += val;
}

template <typename T>
void emthrm::SqrtDecomposition::total_update(const int idx, const T val) {
  lazy[idx] += val;
  to_be_eval[idx] = true;
}

template <typename T>
void emthrm::SqrtDecomposition::partial_query(const int idx, T* val) {
  const int block = idx / block_size;
  if (to_be_eval[block]) {
    for (int i = ls[block]; i < rs[block]; ++i) {
      partial_update(i, lazy[block]);
    }
    lazy[block] = 0;
    to_be_eval[block] = false;
  }
  *val += a[idx];
}

template <typename T>
void emthrm::SqrtDecomposition::total_query(const int idx, T* val) {
  *val += b[idx] + lazy[idx] * (rs[idx] - ls[idx]);
}

int main() {
  int n, q;
  std::cin >> n >> q;
  emthrm::SqrtDecomposition sqrt_decomposition(n);
  a.assign(n, 0);
  b.assign(sqrt_decomposition.n, 0);
  lazy.assign(sqrt_decomposition.n, 0);
  while (q--) {
    int type, s, t;
    std::cin >> type >> s >> t;
    --s; --t;
    if (type == 0) {
      int x;
      std::cin >> x;
      sqrt_decomposition.update(s, t + 1, x);
    } else if (type == 1) {
      std::cout << sqrt_decomposition.query(s, t + 1, 0LL) << '\n';
    }
  }
  return 0;
}
Back to top page