This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub noshi91/Library
#define PROBLEM "https://judge.yosupo.jp/problem/point_set_range_composite" #include "data_structure/segment_tree.cpp" #include "other/affine.cpp" #include "other/modint.cpp" #include <iostream> int main() { #include "other/fast_ios.cpp" int n, q; std::cin >> n >> q; segment_tree<affine_composite_monoid<modint<998244353>>> st(n); for (int i = 0; i != n; i += 1) { int a, b; std::cin >> a >> b; st.update(i, {a, b}); } for (int i = 0; i != q; i += 1) { int t; std::cin >> t; switch (t) { case 0: { int p, c, d; std::cin >> p >> c >> d; st.update(p, {c, d}); } break; case 1: { int l, r, x; std::cin >> l >> r >> x; std::cout << st.fold(l, r).evaluate(x).value() << "\n"; } break; } } }
#line 1 "test/segment_tree.test.cpp" #define PROBLEM "https://judge.yosupo.jp/problem/point_set_range_composite" #line 2 "other/int_alias.cpp" #include <cstddef> #include <cstdint> using i32 = std::int32_t; using i64 = std::int64_t; using u32 = std::uint32_t; using u64 = std::uint64_t; using isize = std::ptrdiff_t; using usize = std::size_t; #line 2 "data_structure/segment_tree.cpp" #include <cassert> #line 5 "data_structure/segment_tree.cpp" #include <vector> template <class M> class segment_tree { using T = typename M::value_type; public: using value_type = T; private: std::vector<T> tree; template <class F> usize search_subtree(usize index, const F f, T fold_l) const { while (index < size()) { const T temp = M::operation(fold_l, tree[index * 2]); if (!f(temp)) { index = index * 2; } else { fold_l = temp; index = index * 2 + 1; } } return index - size(); } public: segment_tree() = default; explicit segment_tree(const usize n) : tree(n * 2, M::identity) {} usize size() const noexcept { return tree.size() / 2; } T fold(usize first, usize last) const { assert(first <= last); assert(last <= size()); first += size(); last += size(); T fold_l = M::identity; T fold_r = M::identity; while (first != last) { if (first % 2 != 0) { fold_l = M::operation(fold_l, tree[first]); first += 1; } first /= 2; if (last % 2 != 0) { last -= 1; fold_r = M::operation(tree[last], fold_r); } last /= 2; } return M::operation(fold_l, fold_r); } template <class F> usize search(usize first, usize last, const F f) const { assert(first <= last); assert(last <= size()); first += size(); last += size(); const usize last_cp = last; usize shift = 0; T fold_l = M::identity; while (first != last) { if (first % 2 != 0) { const T temp = M::operation(fold_l, tree[first]); if (!f(temp)) return search_subtree(first, f, fold_l); fold_l = temp; first += 1; } first /= 2; last /= 2; shift += 1; } while (shift != 0) { shift -= 1; last = last_cp >> shift; if (last % 2 != 0) { last -= 1; const T temp = M::operation(fold_l, tree[last]); if (!f(temp)) return search_subtree(last, f, fold_l); fold_l = temp; } } return last_cp - size(); } void update(usize index, const T x) { assert(index < size()); index += size(); tree[index] = x; while (index != 1) { index /= 2; tree[index] = M::operation(tree[index * 2], tree[index * 2 + 1]); } } }; /** * @brief Segment Tree * @docs docs/segment_tree.md * @see https://scrapbox.io/data-structures/Segment_Tree */ #line 1 "other/affine.cpp" template <class T> class affine { public: T a; T b; constexpr affine(const T &a = 1, const T &b = 0) noexcept : a(a), b(b) {} constexpr T evaluate(const T &x) const noexcept { return x * a + b; } friend constexpr affine operator+(const affine &l, const affine &r) noexcept { return affine(l.a + r.a, l.b + r.b); } constexpr affine composite(const affine &r) const noexcept { return affine(a * r.a, b * r.a + r.b); } }; template <class T> class affine_composite_monoid { public: using value_type = affine<T>; static constexpr value_type operation(const value_type &l, const value_type &r) noexcept { return l.composite(r); } static constexpr value_type identity{}; }; #line 2 "other/modint.cpp" template <std::uint_fast64_t Modulus> class modint { using u64 = std::uint_fast64_t; public: using value_type = u64; static constexpr u64 mod = Modulus; private: static_assert(mod < static_cast<u64>(1) << 32, "Modulus must be less than 2**32"); u64 v; constexpr modint &negate() noexcept { if (v != 0) v = mod - v; return *this; } public: constexpr modint(const u64 x = 0) noexcept : v(x % mod) {} constexpr u64 &value() noexcept { return v; } constexpr const u64 &value() const noexcept { return v; } constexpr modint operator+() const noexcept { return modint(*this); } constexpr modint operator-() const noexcept { return modint(*this).negate(); } constexpr modint operator+(const modint rhs) const noexcept { return modint(*this) += rhs; } constexpr modint operator-(const modint rhs) const noexcept { return modint(*this) -= rhs; } constexpr modint operator*(const modint rhs) const noexcept { return modint(*this) *= rhs; } constexpr modint operator/(const modint rhs) const noexcept { return modint(*this) /= rhs; } constexpr modint &operator+=(const modint rhs) noexcept { v += rhs.v; if (v >= mod) v -= mod; return *this; } constexpr modint &operator-=(const modint rhs) noexcept { if (v < rhs.v) v += mod; v -= rhs.v; return *this; } constexpr modint &operator*=(const modint rhs) noexcept { v = v * rhs.v % mod; return *this; } constexpr modint &operator/=(modint rhs) noexcept { u64 exp = mod - 2; while (exp != 0) { if (exp % 2 != 0) *this *= rhs; rhs *= rhs; exp /= 2; } return *this; } }; template <std::uint_fast64_t Modulus> constexpr typename modint<Modulus>::u64 modint<Modulus>::mod; #line 6 "test/segment_tree.test.cpp" #include <iostream> int main() { #line 1 "other/fast_ios.cpp" std::ios::sync_with_stdio(false); std::cin.tie(nullptr); #line 11 "test/segment_tree.test.cpp" int n, q; std::cin >> n >> q; segment_tree<affine_composite_monoid<modint<998244353>>> st(n); for (int i = 0; i != n; i += 1) { int a, b; std::cin >> a >> b; st.update(i, {a, b}); } for (int i = 0; i != q; i += 1) { int t; std::cin >> t; switch (t) { case 0: { int p, c, d; std::cin >> p >> c >> d; st.update(p, {c, d}); } break; case 1: { int l, r, x; std::cin >> l >> r >> x; std::cout << st.fold(l, r).evaluate(x).value() << "\n"; } break; } } }