#include #include #include #include #include #include #include #include #include #include // #include "Src/Number/IntegerDivision.hpp" // #include "Src/Utility/BinarySearch.hpp" // #include "Src/Sequence/CompressedSequence.hpp" // #include "Src/Sequence/RunLengthEncoding.hpp" // #include "Src/Algebra/Group/AdditiveGroup.hpp" // #include "Src/DataStructure/FenwickTree/FenwickTree.hpp" // #include "Src/DataStructure/SegmentTree/SegmentTree.hpp" // #include "Src/DataStructure/DisjointSetUnion/DisjointSetUnion.hpp" // #include "Src/DataStructure/Heap/BinaryHeap.hpp" #include #include namespace zawa { using i16 = std::int16_t; using i32 = std::int32_t; using i64 = std::int64_t; using i128 = __int128_t; using u8 = std::uint8_t; using u16 = std::uint16_t; using u32 = std::uint32_t; using u64 = std::uint64_t; using usize = std::size_t; } // namespace zawa #include namespace zawa { namespace concepts { template concept Semigroup = requires { typename T::Element; { T::operation(std::declval(), std::declval()) } -> std::same_as; }; } // namespace concepts } // namespace zawa namespace zawa { namespace concepts { template concept Identitiable = requires { typename T::Element; { T::identity() } -> std::same_as; }; template concept Monoid = Semigroup and Identitiable; } // namespace } // namespace zawa namespace zawa { namespace concepts { template concept MonoidWithAction = requires { requires Monoid; requires Monoid; { T::mapping( std::declval(), std::declval() ) } -> std::same_as; }; } // namespace concepts } // namespace zawa #include namespace zawa { template class LazySegmentTree { public: using VM = S::ValueMonoid; using V = typename VM::Element; using OM = S::OperatorMonoid; using O = typename OM::Element; LazySegmentTree() = default; explicit LazySegmentTree(usize n) : m_n{n}, m_sz{1u << (std::bit_width(n))}, m_dat(m_sz << 1, VM::identity()), m_lazy(m_sz << 1, OM::identity()) {} explicit LazySegmentTree(const std::vector& a) : m_n{a.size()}, m_sz{1u << (std::bit_width(a.size()))}, m_dat(m_sz << 1, VM::identity()), m_lazy(m_sz << 1, OM::identity()) { std::ranges::copy(a, m_dat.begin() + inner_size()); for (usize i = inner_size() ; --i ; ) recalc(i); } [[nodiscard]] inline usize size() const noexcept { return m_n; } [[nodiscard]] V operator[](usize i) { assert(i < size()); return get(i, 1, 0, inner_size()); } [[nodiscard]] V get(usize i) { return (*this)[i]; } [[nodiscard]] V product(usize l, usize r) { assert(l <= r and r <= size()); return product(l, r, 1, 0, inner_size()); } void operation(usize l, usize r, const O& o) { assert(l <= r and r <= size()); return operation(l, r, o, 1, 0, inner_size()); } void assign(usize i, const V& v) { assert(i < size()); assign(i, v, 1, 0, inner_size()); } void operation(usize i, const O& o) { assert(i < size()); operation(i, o, 1, 0, inner_size()); } private: using NodeInfo = std::tuple; public: template requires std::predicate usize maxRight(usize l, F f) { assert(l <= size()); if (!f(VM::identity())) return l; if (l == size()) return size(); std::vector ranges; partition_range(l, size(), ranges, 1, 0, inner_size()); V prod = VM::identity(); for (auto [nd, nl, nr] : ranges) { if (!f(VM::operation(prod, m_dat[nd]))) { return maxRight(f, prod, nd, nl, nr); } else { prod = VM::operation(prod, m_dat[nd]); } } return size(); } template requires std::predicate usize minLeft(usize r, F f) { assert(r <= size()); if (!f(VM::identity())) return r; if (!r) return 0; std::vector ranges; partition_range(0, r, ranges, 1, 0, inner_size()); V prod = VM::identity(); for (auto [nd, nl, nr] : ranges | std::views::reverse) { if (!f(VM::operation(m_dat[nd], prod))) { return minLeft(f, prod, nd, nl, nr); } else { prod = VM::operation(prod, m_dat[nd]); } } return 0; } private: usize m_n{}, m_sz{}; std::vector m_dat; std::vector m_lazy; inline usize inner_size() const noexcept { return m_sz; } void recalc(usize nd) { // assert(nd < inner_size()); m_dat[nd] = VM::operation(m_dat[nd << 1 | 0], m_dat[nd << 1 | 1]); } void propagate(usize nd) { // assert(nd < inner_size()); for (usize ch : {nd << 1 | 0, nd << 1 | 1}) { m_dat[ch] = S::mapping(m_dat[ch], m_lazy[nd]); m_lazy[ch] = OM::operation(m_lazy[ch], m_lazy[nd]); } m_lazy[nd] = OM::identity(); } V product(usize ql, usize qr, usize nd, usize nl, usize nr) { if (qr <= nl or nr <= ql) return VM::identity(); if (ql <= nl and nr <= qr) return m_dat[nd]; propagate(nd); const usize m = (nl + nr) >> 1; return VM::operation( product(ql, qr, nd << 1 | 0, nl, m), product(ql, qr, nd << 1 | 1, m, nr) ); } V get(usize i, usize nd, usize nl, usize nr) { if (nd >= inner_size()) return m_dat[nd]; propagate(nd); const usize m = (nl + nr) >> 1; return i < m ? get(i, nd << 1 | 0, nl, m) : get(i, nd << 1 | 1, m, nr); } void operation(usize ql, usize qr, const O& o, usize nd, usize nl, usize nr) { if (qr <= nl or nr <= ql) return; if (ql <= nl and nr <= qr) { m_dat[nd] = S::mapping(m_dat[nd], o); m_lazy[nd] = OM::operation(m_lazy[nd], o); return; } propagate(nd); const usize m = (nl + nr) >> 1; operation(ql, qr, o, nd << 1 | 0, nl, m); operation(ql, qr, o, nd << 1 | 1, m, nr); recalc(nd); } void operation(usize i, const O& o, usize nd, usize nl, usize nr) { if (nl == i and i + 1 == nr) { m_dat[nd] = S::mapping(m_dat[nd], o); return; } propagate(nd); const usize m = (nl + nr) >> 1; i < m ? operation(i, o, nd << 1 | 0, nl, m) : operation(i, o, nd << 1 | 1, m, nr); recalc(nd); } void assign(usize i, const V& v, usize nd, usize nl, usize nr) { if (nl == i and i + 1 == nr) { m_dat[nd] = v; return; } propagate(nd); const usize m = (nl + nr) >> 1; i < m ? assign(i, v, nd << 1 | 0, nl, m) : assign(i, v, nd << 1 | 1, m, nr); recalc(nd); } void partition_range(usize ql, usize qr, std::vector& res, usize nd, usize nl, usize nr) { if (qr <= nl or nr <= ql) return; if (ql <= nl and nr <= qr) { res.emplace_back(nd, nl, nr); return; } propagate(nd); const usize m = (nl + nr) >> 1; partition_range(ql, qr, res, nd << 1 | 0, nl, m); partition_range(ql, qr, res, nd << 1 | 1, m, nr); } template requires std::predicate usize maxRight(F f, const V& prod, usize nd, usize nl, usize nr) { if (nd >= inner_size()) return nl; propagate(nd); const usize m = (nl + nr) >> 1, lch = nd << 1 | 0, rch = nd << 1 | 1; return f(VM::operation(prod, m_dat[lch])) ? maxRight(f, VM::operation(prod, m_dat[lch]), rch, m, nr) : maxRight(f, prod, lch, nl, m); } template requires std::predicate usize minLeft(F f, const V& prod, usize nd, usize nl, usize nr) { if (nd >= inner_size()) return nr; propagate(nd); const usize m = (nl + nr) >> 1, lch = nd << 1 | 0, rch = nd << 1 | 1; return f(VM::operation(m_dat[rch], prod)) ? minLeft(f, VM::operation(m_dat[rch], prod), lch, nl, m) : minLeft(f, prod, rch, m, nr); } }; } // namespace zawa namespace zawa {} using namespace zawa; // #include "atcoder/modint" // using mint = atcoder::modint998244353; // #include // #include // #include // #include // #include // #include // #include // #include // #include // #include // #include // #include // #include // #pragma GCC target("avx2") // #pragma GCC optimize("O3") // #pragma GCC optimize("unroll-loops") using namespace std; template ostream& operator<<(ostream& os, const pair& p) { os << '(' << p.first << ',' << p.second << ')'; return os; } template ostream& operator<<(ostream& os, const vector& v) { for (int i = 0 ; i < ssize(v) ; i++) os << v[i] << (i + 1 == ssize(v) ? "" : " "); return os; } /* * */ int isqrt(int v) { int x = sqrtl(v); while (x * x > v) x--; while ((x+1)*(x+1) <= v) x++; return x; } struct VD { vector sum; int len; }; struct VM { using Element = VD; static Element identity() { return {{0},0}; } static Element operation(Element L, Element R) { while (ssize(L.sum) < ssize(R.sum)) L.sum.push_back(L.sum.back()); while (ssize(L.sum) > ssize(R.sum)) R.sum.push_back(R.sum.back()); for (int i = 0 ; i < ssize(L.sum) ; i++) L.sum[i] += R.sum[i]; L.len += R.len; return L; } }; VM::Element generate(int v) { vector res; // cout << v << " -> "; while (true) { res.push_back(v); if (v <= 1) break; v = isqrt(v); } // cout << res << endl; return {res,1}; } struct OM { using Element = pair; static Element identity() { return {-1,0}; } static Element operation(Element L, Element R) { if (R.first != -1) return R; L.second += R.second; return L; } }; struct ACT { using ValueMonoid = VM; using OperatorMonoid = OM; static ValueMonoid::Element mapping(ValueMonoid::Element v, OperatorMonoid::Element o) { if (o.first != -1) { auto dat = generate(o.first); dat.len = v.len; for (int i = 0 ; i < ssize(dat.sum) ; i++) dat.sum[i] *= v.len; v = move(dat); } assert(ssize(v.sum) >= 1); int op = min(ssize(v.sum)-1,o.second); v.sum.erase(v.sum.begin(),v.sum.begin()+op); return v; } }; int main() { cin.tie(0); cout.tie(0); ios::sync_with_stdio(0); cout << fixed << setprecision(20); #if !defined DEBUG int N,Q; cin >> N >> Q; vector A(N); for (int i = 0 ; i < N ; i++) { int a; cin >> a; A[i] = generate(a); } LazySegmentTree seg(move(A)); while (Q--) { int T,L,R; cin >> T >> L >> R; if (T == 0) cout << seg.product(L,R).sum[0] << '\n'; else if (T == 1) { int x; cin >> x; seg.operation(L,R,{x,0}); } else if (T == 2) seg.operation(L,R,{-1,1}); else assert(0); } #else mt19937_64 mt{random_device{}()}; for (int testcase = 0 ; ; ) { cerr << "----------" << ++testcase << "----------" << endl; auto a = solve(), b = naive(); if (a != b) { // print testcase cerr << "you: " << a << endl; cout << "correct: " << b << endl; exit(0); } } #endif }