Library

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

View the Project on GitHub jellc/Library

:heavy_check_mark: test/library-checker/range_chmin_chmax_add_range_sum.test.cpp

Depends on

Code

#define PROBLEM \
  "https://judge.yosupo.jp/problem/range_chmin_chmax_add_range_sum"

#include <algorithm>
#include <cstdint>
#include <cstdio>
#include <map>

#include "src/data_structure/buckets.hpp"

int main() {
  using namespace workspace;
  using i64 = int64_t;

  int n, q;
  scanf("%d%d", &n, &q);
  std::vector<i64> a(n);
  for (auto&& x : a) {
    scanf("%lld", &x);
  }

  struct data {
    i64 min, max, add, sum, num;
    std::map<i64, i64> map;
  };

  constexpr auto inf = 1'000'000'000'000;

  buckets b(
      begin(a), end(a),
      [](auto l, auto r) {
        data d;
        d.add = 0;
        d.sum = 0;
        d.min = inf;
        d.max = -inf;
        d.num = 0;
        while (l != r) {
          d.sum += *l;
          d.map[*l] += 1;
          d.num += 1;
          ++l;
        }
        return d;
      },
      [](const auto& d, auto l, auto r) {
        while (l != r) {
          *l = std::min(d.min, std::max(d.max, *l)) + d.add;
          ++l;
        }
      });

  for (int t, l, r; q--;) {
    scanf("%d%d%d", &t, &l, &r);
    if (t == 3) {
      i64 sum = 0;
      b(l, r, [&](const auto& x) { sum += x.sum; });
      printf("%lld\n", sum);
      continue;
    }

    i64 a;
    scanf("%lld", &a);
    switch (t) {
      case 0:
        b(l, r, [&](auto& d) {
          auto c = a - d.add;
          if (d.min < c) return;
          d.min = c;
          if (d.max > c) d.max = c;
          while (d.map.rbegin()->first > c) {
            auto [v, k] = *prev(d.map.end());
            d.map.erase(prev(d.map.end()));
            d.map[c] += k;
            d.sum += (c - v) * k;
          }
        });
        break;

      case 1:
        b(l, r, [&](auto& d) {
          auto c = a - d.add;
          if (d.max > c) return;
          d.max = c;
          if (d.min < c) d.min = c;
          while (d.map.begin()->first < c) {
            auto [v, k] = *d.map.begin();
            d.map.erase(d.map.begin());
            d.map[c] += k;
            d.sum += (c - v) * k;
          }
        });
        break;

      case 2:
        b(l, r, [&](auto& x) {
          x.sum += x.num * a;
          x.add += a;
        });
        break;
    }
  }
}
#line 1 "test/library-checker/range_chmin_chmax_add_range_sum.test.cpp"
#define PROBLEM \
  "https://judge.yosupo.jp/problem/range_chmin_chmax_add_range_sum"

#include <algorithm>
#include <cstdint>
#include <cstdio>
#include <map>

#line 2 "src/data_structure/buckets.hpp"

/**
 * @file buckets.hpp
 * @brief Buckets
 */

#include <cmath>
#include <vector>

namespace workspace {

/**
 * @brief Buckets on a sequence.
 */
template <class _Iterator, class _Pack, class _Unpack> struct buckets {
  // Require random access.
  static_assert(
      std::is_same<typename std::iterator_traits<_Iterator>::iterator_category,
                   std::random_access_iterator_tag>::value);

  using difference_type =
      typename std::iterator_traits<_Iterator>::difference_type;

  _Iterator __begin, __end;

  using value_type = decltype(std::declval<_Pack>()(std::declval<_Iterator>(),
                                                    std::declval<_Iterator>()));

  struct bucket {
    value_type __data;
    _Iterator __begin;
    _Iterator __end;
  };

  _Pack __pack;
  _Unpack __unpack;
  difference_type __unit;
  std::vector<bucket> __buckets;

  void prepare() {
    if (!__unit) __unit = round(sqrt(std::distance(__begin, __end)));

    for (auto __l = __begin, __r = __l; __r != __end; __l = __r) {
      for (auto __n = __unit; __r != __end && __n; --__n) ++__r;
      __buckets.push_back({__pack(__l, __r), __l, __r});
    }
  }

 public:
  /**
   * @brief Constuct a new buckets object.
   */
  buckets(_Iterator __first, _Iterator __last, _Pack __pack, _Unpack __unpack,
          difference_type __unit = 0)
      : __begin(__first),
        __end(__last),
        __pack(__pack),
        __unpack(__unpack),
        __unit(__unit) {
    prepare();
  }

  /**
   * @brief Number of buckets.
   */
  auto size() const { return __buckets.size(); }

  bool empty() const { return __begin == __end; }

  /**
   * @brief Operate on a subsegment.
   *
   * @param __first
   * @param __last
   * @param __oper
   */
  template <class _Operator>
  void operator()(_Iterator __first, _Iterator __last, _Operator __oper) {
    if (__first == __last) return;

    auto __index = std::distance(__begin, __first);
    auto __b = std::next(__buckets.begin(), __index / __unit);

    if (__index % __unit) {
      __unpack(__b->__data, __b->__begin, __b->__end);

      auto __mid = std::distance(__last, __b->__end) > 0 ? __last : __b->__end;

      auto __tmp = __pack(__first, __mid);
      __oper(__tmp);
      __unpack(__tmp, __first, __mid);

      __b->__data = __pack(__b->__begin, __b->__end);
      ++__b;
    }

    while (true) {
      if (__b == __buckets.end()) return;
      if (std::distance(__b->__end, __last) < 0) break;

      __oper(__b->__data);
      ++__b;
    }

    if (std::distance(__b->__begin, __last) > 0) {
      __unpack(__b->__data, __b->__begin, __b->__end);

      auto __tmp = __pack(__b->__begin, __last);
      __oper(__tmp);
      __unpack(__tmp, __b->__begin, __last);

      __b->__data = __pack(__b->__begin, __b->__end);
    }
  }

  /**
   * @brief Operate on a point.
   *
   * @param __pos
   * @param __oper
   */
  template <class _Operator>
  void operator()(_Iterator __pos, _Operator __oper) {
    auto __index = std::distance(__begin, __pos);
    auto __b = std::next(__buckets.begin(), __index / __unit);

    __unpack(__b->__data, __b->__begin, __b->__end);
    __oper(*__pos);
    __b->__data = __pack(__b->__begin, __b->__end);
  }

  /**
   * @brief Operate on a subsegment.
   *
   * @param __i
   * @param __j
   * @param __oper
   */
  template <class _Operator>
  void operator()(difference_type __i, difference_type __j, _Operator __oper) {
    operator()(std::next(__begin, __i), std::next(__begin, __j), __oper);
  }

  /**
   * @brief Operate on a point.
   *
   * @param __pos
   * @param __oper
   */
  template <class _Operator>
  void operator()(difference_type __i, _Operator __oper) {
    operator()(std::next(__begin, __i), __oper);
  }
};

}  // namespace workspace
#line 10 "test/library-checker/range_chmin_chmax_add_range_sum.test.cpp"

int main() {
  using namespace workspace;
  using i64 = int64_t;

  int n, q;
  scanf("%d%d", &n, &q);
  std::vector<i64> a(n);
  for (auto&& x : a) {
    scanf("%lld", &x);
  }

  struct data {
    i64 min, max, add, sum, num;
    std::map<i64, i64> map;
  };

  constexpr auto inf = 1'000'000'000'000;

  buckets b(
      begin(a), end(a),
      [](auto l, auto r) {
        data d;
        d.add = 0;
        d.sum = 0;
        d.min = inf;
        d.max = -inf;
        d.num = 0;
        while (l != r) {
          d.sum += *l;
          d.map[*l] += 1;
          d.num += 1;
          ++l;
        }
        return d;
      },
      [](const auto& d, auto l, auto r) {
        while (l != r) {
          *l = std::min(d.min, std::max(d.max, *l)) + d.add;
          ++l;
        }
      });

  for (int t, l, r; q--;) {
    scanf("%d%d%d", &t, &l, &r);
    if (t == 3) {
      i64 sum = 0;
      b(l, r, [&](const auto& x) { sum += x.sum; });
      printf("%lld\n", sum);
      continue;
    }

    i64 a;
    scanf("%lld", &a);
    switch (t) {
      case 0:
        b(l, r, [&](auto& d) {
          auto c = a - d.add;
          if (d.min < c) return;
          d.min = c;
          if (d.max > c) d.max = c;
          while (d.map.rbegin()->first > c) {
            auto [v, k] = *prev(d.map.end());
            d.map.erase(prev(d.map.end()));
            d.map[c] += k;
            d.sum += (c - v) * k;
          }
        });
        break;

      case 1:
        b(l, r, [&](auto& d) {
          auto c = a - d.add;
          if (d.max > c) return;
          d.max = c;
          if (d.min < c) d.min = c;
          while (d.map.begin()->first < c) {
            auto [v, k] = *d.map.begin();
            d.map.erase(d.map.begin());
            d.map[c] += k;
            d.sum += (c - v) * k;
          }
        });
        break;

      case 2:
        b(l, r, [&](auto& x) {
          x.sum += x.num * a;
          x.add += a;
        });
        break;
    }
  }
}
Back to top page