matsutaku-library

This documentation is automatically generated by competitive-verifier/competitive-verifier

View the Project on GitHub MatsuTaku/matsutaku-library

:heavy_check_mark: test/yosupo/range_affine_range_sum.test.cpp

Code

#define PROBLEM "https://judge.yosupo.jp/problem/range_affine_range_sum"
#include "include/mtl/lazy_segment_tree.hpp"
#include "include/mtl/modular.hpp"
#include <bits/stdc++.h>

using namespace std;
using ll = long long;
constexpr ll MOD = 998244353;
using mint = Modular<MOD>;

struct Sum {
  mint a=0;
  int sz=0;
  Sum operator*(const Sum& r) const {
    return {a+r.a, sz+r.sz};
  }
};

struct Affine {
  mint b=1, c=0;
  Affine& operator*=(const Affine& r) {
    b *= r.b;
    c = c*r.b + r.c;
    return *this;
  }
  Sum act(const Sum& a) const {
    return {b*a.a + c*a.sz, a.sz};
  }
};

int main() {
  cin.tie(nullptr); ios::sync_with_stdio(false);

  int N,Q; cin>>N>>Q;
  vector<Sum> A(N); 
  for (auto& a : A) {
    cin>>a.a;
    a.sz = 1;
  }
  SegmentTreebase<Sum, Affine> rsq(A.begin(), A.end());

  for (int q = 0; q < Q; q++) {
    int t; cin>>t;
    if (t == 0) {
      int l,r,b,c; cin>>l>>r>>b>>c;
      rsq.update(l,r, {b,c});
    } else if (t == 1) {
      int l,r; cin>>l>>r;
      auto ans = rsq.query(l,r);
      cout << ans.a << endl;
    }
  }

  return 0;
}
#line 1 "test/yosupo/range_affine_range_sum.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/range_affine_range_sum"
#line 2 "include/mtl/bit_manip.hpp"
#include <cstdint>
#include <cassert>
#if __cplusplus >= 202002L
#ifndef MTL_CPP20
#define MTL_CPP20
#endif
#include <bit>
#endif

namespace bm {

/// Count 1s for each 8 bits
inline constexpr uint64_t popcnt_e8(uint64_t x) {
  x = (x & 0x5555555555555555) + ((x>>1) & 0x5555555555555555);
  x = (x & 0x3333333333333333) + ((x>>2) & 0x3333333333333333);
  x = (x & 0x0F0F0F0F0F0F0F0F) + ((x>>4) & 0x0F0F0F0F0F0F0F0F);
  return x;
}
/// Count 1s
inline constexpr unsigned popcnt(uint64_t x) {
#ifdef MTL_CPP20
  return std::popcount(x);
#else
  return (popcnt_e8(x) * 0x0101010101010101) >> 56;
#endif
}
/// Alias to mtl::popcnt(x)
constexpr unsigned popcount(uint64_t x) {
  return popcnt(x);
}
/// Count trailing 0s. s.t. *11011000 -> 3
inline constexpr unsigned ctz(uint64_t x) {
#ifdef MTL_CPP20
  return std::countr_zero(x);
#else
  return popcnt((x & (-x)) - 1);
#endif
}
/// Alias to mtl::ctz(x)
constexpr unsigned countr_zero(uint64_t x) {
  return ctz(x);
}
/// Count trailing 1s. s.t. *11011011 -> 2
inline constexpr unsigned cto(uint64_t x) {
#ifdef MTL_CPP20
  return std::countr_one(x);
#else
  return ctz(~x);
#endif
}
/// Alias to mtl::cto(x)
constexpr unsigned countr_one(uint64_t x) {
  return cto(x);
}
inline constexpr unsigned ctz8(uint8_t x) {
  return x == 0 ? 8 : popcnt_e8((x & (-x)) - 1);
}
/// [00..0](8bit) -> 0, [**..*](not only 0) -> 1
inline constexpr uint8_t summary(uint64_t x) {
  constexpr uint64_t hmask = 0x8080808080808080ull;
  constexpr uint64_t lmask = 0x7F7F7F7F7F7F7F7Full;
  auto a = x & hmask;
  auto b = x & lmask;
  b = hmask - b;
  b = ~b;
  auto c = (a | b) & hmask;
  c *= 0x0002040810204081ull;
  return uint8_t(c >> 56);
}
/// Extract target area of bits
inline constexpr uint64_t bextr(uint64_t x, unsigned start, unsigned len) {
  uint64_t mask = len < 64 ? (1ull<<len)-1 : 0xFFFFFFFFFFFFFFFFull;
  return (x >> start) & mask;
}
/// 00101101 -> 00111111 -count_1s-> 6
inline constexpr unsigned log2p1(uint8_t x) {
  if (x & 0x80)
    return 8;
  uint64_t p = uint64_t(x) * 0x0101010101010101ull;
  p -= 0x8040201008040201ull;
  p = ~p & 0x8080808080808080ull;
  p = (p >> 7) * 0x0101010101010101ull;
  p >>= 56;
  return p;
}
/// 00101100 -mask_mssb-> 00100000 -to_index-> 5
inline constexpr unsigned mssb8(uint8_t x) {
  assert(x != 0);
  return log2p1(x) - 1;
}
/// 00101100 -mask_lssb-> 00000100 -to_index-> 2
inline constexpr unsigned lssb8(uint8_t x) {
  assert(x != 0);
  return popcnt_e8((x & -x) - 1);
}
/// Count leading 0s. 00001011... -> 4
inline constexpr unsigned clz(uint64_t x) {
#ifdef MTL_CPP20
  return std::countl_zero(x);
#else
  if (x == 0)
    return 64;
  auto i = mssb8(summary(x));
  auto j = mssb8(bextr(x, 8 * i, 8));
  return 63 - (8 * i + j);
#endif
}
/// Alias to mtl::clz(x)
constexpr unsigned countl_zero(uint64_t x) {
  return clz(x);
}
/// Count leading 1s. 11110100... -> 4
inline constexpr unsigned clo(uint64_t x) {
#ifdef MTL_CPP20
  return std::countl_one(x);
#else
  return clz(~x);
#endif
}
/// Alias to mtl::clo(x)
constexpr unsigned countl_one(uint64_t x) {
  return clo(x);
}

inline constexpr unsigned clz8(uint8_t x) {
  return x == 0 ? 8 : 7 - mssb8(x);
}
inline constexpr uint64_t bit_reverse(uint64_t x) {
  x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32);
  x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16);
  x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8);
  x = ((x & 0x0F0F0F0F0F0F0F0F) << 4) | ((x & 0xF0F0F0F0F0F0F0F0) >> 4);
  x = ((x & 0x3333333333333333) << 2) | ((x & 0xCCCCCCCCCCCCCCCC) >> 2);
  x = ((x & 0x5555555555555555) << 1) | ((x & 0xAAAAAAAAAAAAAAAA) >> 1);
  return x;
}

/// Check if x is power of 2. 00100000 -> true, 00100001 -> false
constexpr bool has_single_bit(uint64_t x) noexcept {
#ifdef MTL_CPP20
  return std::has_single_bit(x);
#else
  return x != 0 && (x & (x - 1)) == 0;
#endif
}

/// Bit width needs to represent x. 00110110 -> 6
constexpr int bit_width(uint64_t x) noexcept {
#ifdef MTL_CPP20
  return std::bit_width(x);
#else
  return 64 - clz(x);
#endif
}

/// Ceil power of 2. 00110110 -> 01000000
constexpr uint64_t bit_ceil(uint64_t x) {
#ifdef MTL_CPP20
  return std::bit_ceil(x);
#else
  if (x == 0) return 1;
  return 1ull << bit_width(x - 1);
#endif
}

/// Floor power of 2. 00110110 -> 00100000
constexpr uint64_t bit_floor(uint64_t x) {
#ifdef MTL_CPP20
  return std::bit_floor(x);
#else
  if (x == 0) return 0;
  return 1ull << (bit_width(x) - 1);
#endif
}

} // namespace bm
#line 3 "include/mtl/lazy_segment_tree.hpp"
// #include "monoid.hpp"
#include <cstddef>
#include <utility>
#include <vector>
#include <stack>
#line 9 "include/mtl/lazy_segment_tree.hpp"
#if __cpp_concepts >= 202002L
#include <concepts>

template<typename M>
concept LazySegmentTreeMonoid = requires (M m) {
  {m * m} -> std::same_as<M>;
};
template<typename A, typename M>
concept LazySegmentTreeOperatorMonoid = requires(A a, M m) {
  {a *= a} -> std::same_as<A&>;
  {a.act(m)} -> std::same_as<M>;
};
#endif

template <typename M, typename A>
#if __cpp_concepts >= 202002L
requires LazySegmentTreeMonoid<M> &&
         LazySegmentTreeOperatorMonoid<A,M>
#endif
class SegmentTreebase {
 private:
  size_t size_;
  std::vector<std::pair<M, A>> tree_;
  std::vector<size_t> ids_;

 public:
  explicit SegmentTreebase(size_t size) :
      size_(1ull<<(64-bm::clz(size-1))),
      tree_(size_*2) {
    ids_.reserve((64-bm::clz(size-1))*2);
  }

  template <typename Iter>
  explicit SegmentTreebase(Iter begin, Iter end)
    : SegmentTreebase(std::distance(begin, end)) {
    static_assert(std::is_convertible<typename std::iterator_traits<Iter>::value_type, M>::value, "");
    for (auto it = begin; it != end; ++it) {
      tree_[size_ + it - begin].first = *it;
    }
    for (size_t i = size_-1; i > 0; i--) {
      tree_[i].first = tree_[i*2].first * tree_[i*2+1].first;
    }
  }

  inline void range_update(size_t l, size_t r, const A& e) {
    assert(l <= r);
    assert(r <= size_);
    if (l == r) return;
    _lazy_propagation(l, r);

    for (size_t _l=l+size_, _r=r+size_; _l<_r; _l>>=1, _r>>=1) {
      if (_l&1) 
        tree_[_l++].second *= e;
      if (_r&1) 
        tree_[--_r].second *= e;
    }

    for (auto id : ids_) {
      _propagate(id*2);
      _propagate(id*2+1);
      tree_[id].first = tree_[id*2].first * tree_[id*2+1].first;
    }
  }
  inline void update(size_t l, size_t r, const A& e) {
    range_update(l, r, e);
  }
  inline void update(size_t i, const A& e) {
    range_update(i, i+1, e);
  }

  template<typename T>
  inline void set(size_t i, T&& e) {
    _lazy_propagation(i, i+1);
    int u = i+size_;
    tree_[u].first = M(std::forward<T>(e));
    u >>= 1;
    while (u > 0) {
      tree_[u].first = tree_[u*2].first * tree_[u*2+1].first;
      u >>= 1;
    }
  }

  inline M query(size_t l, size_t r) {
    _lazy_propagation(l, r);

    M lhs,rhs;
    for (size_t _l=l+size_, _r=r+size_; _l<_r; _l>>=1, _r>>=1) {
      if (_l&1) {
        _propagate(_l);
        lhs = lhs * tree_[_l].first;
        ++_l;
      }
      if (_r&1) {
        --_r;
        _propagate(_r);
        rhs = tree_[_r].first * rhs;
      }
    }
    return lhs * rhs;
  }
  /// Alias for query(l, r)
  M prod(size_t l, size_t r) {
    return query(l, r);
  }

  inline const M& get(size_t index) {
    _lazy_propagation(index, index+1);
    auto l = index+size_;
    _propagate(l);
    return tree_[l].first;
  }

 private:
  void _set_ids(size_t l, size_t r) {
    ids_.clear();
    auto _l=l+size_, _r=r+size_;
    auto lth = _l/(_l&(-_l))/2;
    auto rth = _r/(_r&(-_r))/2;
    for (; _l<_r; _l>>=1, _r>>=1) {
      if (_r <= rth) ids_.push_back(_r);
      if (_l <= lth) ids_.push_back(_l);
    }
    for (; _l>0; _l>>=1)
      ids_.push_back(_l);
  }

  inline void _propagate(size_t id) {
    A& e = tree_[id].second;
    tree_[id].first = e.act(tree_[id].first);
    if (id < size_) {
      tree_[id*2].second *= e;
      tree_[id*2+1].second *= e;
    }
    tree_[id].second = A();
  }

  void _lazy_propagation(size_t l, size_t r) {
    if (l == r) return;
    _set_ids(l, r);
    for (auto it = ids_.rbegin(); it != ids_.rend(); ++it)
      _propagate(*it);
  }

 public:
  template<class F>
  size_t max_right(size_t begin, size_t end, F f) {
    if (begin == end) return end;
    M p;
    std::stack<std::pair<size_t, M>> rps;
    auto l = size_ + begin;
    auto r = size_ + end;
    _lazy_propagation(begin, end);
    auto access = [&](size_t i) {
      _propagate(i);
      return tree_[i].first;
    };
    while (l < r and f(p * access(l))) {
      if (l&1) p = p * tree_[l++].first;
      if (r&1) {
        rps.emplace(r, access(r-1));
        r--;
      }
      l>>=1; r>>=1;
    }
    if (l >= r) {
      while (rps.size()) {
        auto& [r, rp] = rps.top();
        if (!f(p * rp)) {
          l = r-1;
          break;
        }
        p = p * rp;
        rps.pop();
      }
      if (rps.empty()) return end;
    }
    while (l < size_) {
      assert(!f(p * access(l)));
      l <<= 1;
      auto pl = access(l);
      if (f(p * pl)) {
        p = p * pl;
        l++;
      }
    }
    return l - size_;
  }
  template<bool (*F)(M)>
  size_t max_right(size_t begin, size_t end) {
    return max_right(begin, end, [](M x) { return F(x); });
  }

  template<class F>
  size_t min_left(size_t begin, size_t end, F f) {
    if (end == begin) return begin;
    M p;
    std::stack<std::pair<size_t, M>> lps;
    auto l = size_ + begin;
    auto r = size_ + end;
    _lazy_propagation(begin, end);
    auto access = [&](size_t i) {
      _propagate(i);
      return tree_[i].first;
    };
    while (l < r and f(access(r-1) * p)) {
      if (l&1) {
        lps.emplace(l, access(l));
        l++;
      }
      if (r&1) p = tree_[r-1].first * p;
      l>>=1; r>>=1;
    }
    if (l >= r) {
      while (lps.size()) {
        auto& [l, lp] = lps.top();
        if (!f(lp * p)) {
          r = l+1;
          break;
        }
        p = lp * p;
        lps.pop();
      }
      if (lps.empty()) return begin;
    }
    while (r <= size_) {
      assert(!f(access(r-1) * p));
      r <<= 1;
      auto pr = access(r-1);
      if (f(pr * p)) {
        p = pr * p;
        --r;
      }
    }
    return r - size_;
  }
  template<bool (*F)(M)>
  size_t min_left(size_t begin, size_t end) {
    return min_left(begin, [](M x) { return F(x); });
  }

};

#line 3 "include/mtl/modular.hpp"
#include <iostream>
#line 5 "include/mtl/modular.hpp"

template <int MOD>
class Modular {
 private:
  unsigned int val_;

 public:
  static constexpr unsigned int mod() { return MOD; }
  template<class T>
  static constexpr unsigned int safe_mod(T v) {
    auto x = (long long)(v%(long long)mod());
    if (x < 0) x += mod();
    return (unsigned int) x;
  }

  constexpr Modular() : val_(0) {}
  template<class T,
      std::enable_if_t<
          std::is_integral<T>::value && std::is_unsigned<T>::value
      > * = nullptr>
  constexpr Modular(T v) : val_(v%mod()) {}
  template<class T,
      std::enable_if_t<
          std::is_integral<T>::value && !std::is_unsigned<T>::value
      > * = nullptr>
  constexpr Modular(T v) : val_(safe_mod(v)) {}

  constexpr unsigned int val() const { return val_; }
  constexpr Modular& operator+=(Modular x) {
    val_ += x.val();
    if (val_ >= mod()) val_ -= mod();
    return *this;
  }
  constexpr Modular operator-() const { return {mod() - val_}; }
  constexpr Modular& operator-=(Modular x) {
    val_ += mod() - x.val();
    if (val_ >= mod()) val_ -= mod();
    return *this;
  }
  constexpr Modular& operator*=(Modular x) {
    auto v = (long long) val_ * x.val();
    if (v >= mod()) v %= mod();
    val_ = v;
    return *this;
  }
  constexpr Modular pow(long long p) const {
    assert(p >= 0);
    Modular t = 1;
    Modular u = *this;
    while (p) {
      if (p & 1)
        t *= u;
      u *= u;
      p >>= 1;
    }
    return t;
  }
  friend constexpr Modular pow(Modular x, long long p) {
    return x.pow(p);
  }
  constexpr Modular inv() const { return pow(mod()-2); }
  constexpr Modular& operator/=(Modular x) { return *this *= x.inv(); }
  constexpr Modular operator+(Modular x) const { return Modular(*this) += x; }
  constexpr Modular operator-(Modular x) const { return Modular(*this) -= x; }
  constexpr Modular operator*(Modular x) const { return Modular(*this) *= x; }
  constexpr Modular operator/(Modular x) const { return Modular(*this) /= x; }
  constexpr Modular& operator++() { return *this += 1; }
  constexpr Modular operator++(int) { Modular c = *this; ++(*this); return c; }
  constexpr Modular& operator--() { return *this -= 1; }
  constexpr Modular operator--(int) { Modular c = *this; --(*this); return c; }

  constexpr bool operator==(Modular x) const { return val() == x.val(); }
  constexpr bool operator!=(Modular x) const { return val() != x.val(); }

  constexpr bool is_square() const {
    return pow((mod()-1)/2) == 1;
  }
  /**
   * Return x s.t. x * x = a mod p
   * reference: https://zenn.dev/peria/articles/c6afc72b6b003c
  */
  constexpr Modular sqrt() const {
    if (!is_square()) 
      throw std::runtime_error("not square");
    auto mod_eight = mod() % 8;
    if (mod_eight == 3 || mod_eight == 7) {
      return pow((mod()+1)/4);
    } else if (mod_eight == 5) {
      auto x = pow((mod()+3)/8);
      if (x * x != *this)
        x *= Modular(2).pow((mod()-1)/4);
      return x;
    } else {
      Modular d = 2;
      while (d.is_square())
        d += 1;
      auto t = mod()-1;
      int s = bm::ctz(t);
      t >>= s;
      auto a = pow(t);
      auto D = d.pow(t);
      int m = 0;
      Modular dt = 1;
      Modular du = D;
      for (int i = 0; i < s; i++) {
        if ((a*dt).pow(1u<<(s-1-i)) == -1) {
          m |= 1u << i;
          dt *= du;
        }
        du *= du;
      }
      return pow((t+1)/2) * D.pow(m/2);
    }
  }

  friend std::ostream& operator<<(std::ostream& os, const Modular& x) {
    return os << x.val();
  }
  friend std::istream& operator>>(std::istream& is, Modular& x) {
    return is >> x.val_;
  }

};

using Modular998244353 = Modular<998244353>;
using Modular1000000007 = Modular<(int)1e9+7>;

template<int Id=0>
class DynamicModular {
 private:
  static unsigned int mod_;
  unsigned int val_;

 public:
  static unsigned int mod() { return mod_; }
  static void set_mod(unsigned int m) { mod_ = m; }
  template<class T>
  static constexpr unsigned int safe_mod(T v) {
    auto x = (long long)(v%(long long)mod());
    if (x < 0) x += mod();
    return (unsigned int) x;
  }

  constexpr DynamicModular() : val_(0) {}
  template<class T,
      std::enable_if_t<
          std::is_integral<T>::value && std::is_unsigned<T>::value
      > * = nullptr>
  constexpr DynamicModular(T v) : val_(v%mod()) {}
  template<class T,
      std::enable_if_t<
          std::is_integral<T>::value && !std::is_unsigned<T>::value
      > * = nullptr>
  constexpr DynamicModular(T v) : val_(safe_mod(v)) {}

  constexpr unsigned int val() const { return val_; }
  constexpr DynamicModular& operator+=(DynamicModular x) {
    val_ += x.val();
    if (val_ >= mod()) val_ -= mod();
    return *this;
  }
  constexpr DynamicModular operator-() const { return {mod() - val_}; }
  constexpr DynamicModular& operator-=(DynamicModular x) {
    val_ += mod() - x.val();
    if (val_ >= mod()) val_ -= mod();
    return *this;
  }
  constexpr DynamicModular& operator*=(DynamicModular x) {
    auto v = (long long) val_ * x.val();
    if (v >= mod()) v %= mod();
    val_ = v;
    return *this;
  }
  constexpr DynamicModular pow(long long p) const {
    assert(p >= 0);
    DynamicModular t = 1;
    DynamicModular u = *this;
    while (p) {
      if (p & 1)
        t *= u;
      u *= u;
      p >>= 1;
    }
    return t;
  }
  friend constexpr DynamicModular pow(DynamicModular x, long long p) {
    return x.pow(p);
  }
  // TODO: implement when mod is not prime
  constexpr DynamicModular inv() const { return pow(mod()-2); }
  constexpr DynamicModular& operator/=(DynamicModular x) { return *this *= x.inv(); }
  constexpr DynamicModular operator+(DynamicModular x) const { return DynamicModular(*this) += x; }
  constexpr DynamicModular operator-(DynamicModular x) const { return DynamicModular(*this) -= x; }
  constexpr DynamicModular operator*(DynamicModular x) const { return DynamicModular(*this) *= x; }
  constexpr DynamicModular operator/(DynamicModular x) const { return DynamicModular(*this) /= x; }
  constexpr DynamicModular& operator++() { return *this += 1; }
  constexpr DynamicModular operator++(int) { DynamicModular c = *this; ++(*this); return c; }
  constexpr DynamicModular& operator--() { return *this -= 1; }
  constexpr DynamicModular operator--(int) { DynamicModular c = *this; --(*this); return c; }

  constexpr bool operator==(DynamicModular x) const { return val() == x.val(); }
  constexpr bool operator!=(DynamicModular x) const { return val() != x.val(); }

  constexpr bool is_square() const {
    return val() == 0 or pow((mod()-1)/2) == 1;
  }
  /**
   * Return x s.t. x * x = a mod p
   * reference: https://zenn.dev/peria/articles/c6afc72b6b003c
  */
  constexpr DynamicModular sqrt() const {
    // assert mod is prime
    if (!is_square()) 
      throw std::runtime_error("not square");
    if (val() < 2)
      return val();
    auto mod_eight = mod() % 8;
    if (mod_eight == 3 || mod_eight == 7) {
      return pow((mod()+1)/4);
    } else if (mod_eight == 5) {
      auto x = pow((mod()+3)/8);
      if (x * x != *this)
        x *= DynamicModular(2).pow((mod()-1)/4);
      return x;
    } else {
      DynamicModular d = 2;
      while (d.is_square())
        ++d;
      auto t = mod()-1;
      int s = bm::ctz(t);
      t >>= s;
      auto a = pow(t);
      auto D = d.pow(t);
      int m = 0;
      DynamicModular dt = 1;
      DynamicModular du = D;
      for (int i = 0; i < s; i++) {
        if ((a*dt).pow(1u<<(s-1-i)) == -1) {
          m |= 1u << i;
          dt *= du;
        }
        du *= du;
      }
      return pow((t+1)/2) * D.pow(m/2);
    }
  }

  friend std::ostream& operator<<(std::ostream& os, const DynamicModular& x) {
    return os << x.val();
  }
  friend std::istream& operator>>(std::istream& is, DynamicModular& x) {
    return is >> x.val_;
  }

};
template<int Id>
unsigned int DynamicModular<Id>::mod_;

#line 264 "include/mtl/modular.hpp"

template<class ModInt>
struct ModularUtil {
  static constexpr int mod = ModInt::mod();
  static struct inv_table {
    std::vector<ModInt> tb{0,1};
    inv_table() : tb({0,1}) {}
  } inv_;
  void set_inv(int n) {
    int m = inv_.tb.size();
    if (m > n) return;
    inv_.tb.resize(n+1);
    for (int i = m; i < n+1; i++)
      inv_.tb[i] = -inv_.tb[mod % i] * (mod / i);
  }
  ModInt& inv(int i) {
    set_inv(i);
    return inv_.tb[i];
  }
};
template<class ModInt>
typename ModularUtil<ModInt>::inv_table ModularUtil<ModInt>::inv_;

#include <array>

namespace math {

constexpr int mod_pow_constexpr(int x, int p, int m) {
  long long t = 1;
  long long u = x;
  while (p) {
    if (p & 1) {
      t *= u;
      t %= m;
    }
    u *= u;
    u %= m;
    p >>= 1;
  }
  return (int) t;
}

constexpr int primitive_root_constexpr(int m) {
  if (m == 2) return 1;
  if (m == 167772161) return 3;
  if (m == 469762049) return 3;
  if (m == 754974721) return 11;
  if (m == 880803841) return 26;
  if (m == 998244353) return 3;

  std::array<int, 20> divs{};
  int cnt = 0;
  int x = m-1;
  if (x % 2 == 0) {
    divs[cnt++] = 2;
    x >>= bm::ctz(x);
  }
  for (int d = 3; d*d <= x; d += 2) {
    if (x % d == 0) {
      divs[cnt++] = d;
      while (x % d == 0)
        x /= d;
    }
  }
  if (x > 1) divs[cnt++] = x;
  for (int g = 2; g < m; g++) {
    bool ok = true;
    for (int i = 0; i < cnt; i++) {
      if (mod_pow_constexpr(g, (m-1) / divs[i], m) == 1) {
        ok = false;
        break;
      }
    }
    if (ok) return g;
  }
  return -1;
}

template<int m>
constexpr int primitive_root = primitive_root_constexpr(m);

}
#line 4 "test/yosupo/range_affine_range_sum.test.cpp"
#include <bits/stdc++.h>

using namespace std;
using ll = long long;
constexpr ll MOD = 998244353;
using mint = Modular<MOD>;

struct Sum {
  mint a=0;
  int sz=0;
  Sum operator*(const Sum& r) const {
    return {a+r.a, sz+r.sz};
  }
};

struct Affine {
  mint b=1, c=0;
  Affine& operator*=(const Affine& r) {
    b *= r.b;
    c = c*r.b + r.c;
    return *this;
  }
  Sum act(const Sum& a) const {
    return {b*a.a + c*a.sz, a.sz};
  }
};

int main() {
  cin.tie(nullptr); ios::sync_with_stdio(false);

  int N,Q; cin>>N>>Q;
  vector<Sum> A(N); 
  for (auto& a : A) {
    cin>>a.a;
    a.sz = 1;
  }
  SegmentTreebase<Sum, Affine> rsq(A.begin(), A.end());

  for (int q = 0; q < Q; q++) {
    int t; cin>>t;
    if (t == 0) {
      int l,r,b,c; cin>>l>>r>>b>>c;
      rsq.update(l,r, {b,c});
    } else if (t == 1) {
      int l,r; cin>>l>>r;
      auto ans = rsq.query(l,r);
      cout << ans.a << endl;
    }
  }

  return 0;
}

Test cases

Env Name Status Elapsed Memory
g++ example_00 :heavy_check_mark: AC 6 ms 3 MB
g++ max_random_00 :heavy_check_mark: AC 1099 ms 24 MB
g++ max_random_01 :heavy_check_mark: AC 1254 ms 24 MB
g++ max_random_02 :heavy_check_mark: AC 1260 ms 24 MB
g++ random_00 :heavy_check_mark: AC 917 ms 23 MB
g++ random_01 :heavy_check_mark: AC 953 ms 23 MB
g++ random_02 :heavy_check_mark: AC 762 ms 6 MB
g++ small_00 :heavy_check_mark: AC 7 ms 3 MB
g++ small_01 :heavy_check_mark: AC 6 ms 3 MB
g++ small_02 :heavy_check_mark: AC 6 ms 3 MB
g++ small_03 :heavy_check_mark: AC 6 ms 3 MB
g++ small_04 :heavy_check_mark: AC 6 ms 3 MB
g++ small_05 :heavy_check_mark: AC 6 ms 3 MB
g++ small_06 :heavy_check_mark: AC 7 ms 3 MB
g++ small_07 :heavy_check_mark: AC 7 ms 3 MB
g++ small_08 :heavy_check_mark: AC 7 ms 3 MB
g++ small_09 :heavy_check_mark: AC 6 ms 3 MB
g++ small_random_00 :heavy_check_mark: AC 8 ms 4 MB
g++ small_random_01 :heavy_check_mark: AC 7 ms 3 MB
clang++ example_00 :heavy_check_mark: AC 6 ms 3 MB
clang++ max_random_00 :heavy_check_mark: AC 1226 ms 24 MB
clang++ max_random_01 :heavy_check_mark: AC 1185 ms 24 MB
clang++ max_random_02 :heavy_check_mark: AC 1185 ms 24 MB
clang++ random_00 :heavy_check_mark: AC 932 ms 23 MB
clang++ random_01 :heavy_check_mark: AC 1157 ms 23 MB
clang++ random_02 :heavy_check_mark: AC 779 ms 6 MB
clang++ small_00 :heavy_check_mark: AC 6 ms 3 MB
clang++ small_01 :heavy_check_mark: AC 6 ms 3 MB
clang++ small_02 :heavy_check_mark: AC 6 ms 3 MB
clang++ small_03 :heavy_check_mark: AC 6 ms 3 MB
clang++ small_04 :heavy_check_mark: AC 6 ms 3 MB
clang++ small_05 :heavy_check_mark: AC 6 ms 3 MB
clang++ small_06 :heavy_check_mark: AC 6 ms 3 MB
clang++ small_07 :heavy_check_mark: AC 6 ms 3 MB
clang++ small_08 :heavy_check_mark: AC 6 ms 3 MB
clang++ small_09 :heavy_check_mark: AC 6 ms 3 MB
clang++ small_random_00 :heavy_check_mark: AC 7 ms 4 MB
clang++ small_random_01 :heavy_check_mark: AC 7 ms 3 MB
Back to top page