#include #include #include #include using namespace std; template class LazySegTree { private: const T et; const X ex; int num; std::vector dat; std::vector lazy; T (*const eval)(const T, const T) {}; T (*const fa)(const T, const X) {}; X (*const fm)(const X, const X) {}; X (*const fp)(const X, int) {}; public: LazySegTree(std::vector &v, T Et, X Ex, T (*valcal)(T, T), T (*lazyupdate)(T, X), X (*lazypropagation)(X, X), X (*rangelazy)(X, int)) : et(Et), ex(Ex), eval(valcal), fa(lazyupdate), fm(lazypropagation), fp(rangelazy) { int siz = static_cast(v.size()); for (num = 1; num < siz; num <<= 1); dat = std::vector (2 * num - 1, et); lazy = std::vector (2 * num - 1, ex); for (int i = 0; i < siz; ++i) dat[i + num - 1] = v[i]; for (int i = num - 2; i >= 0; --i) dat[i] = eval(dat[i * 2 + 1], dat[i * 2 + 2]); } LazySegTree(int n, T Et, X Ex, T (*valcal)(T, T), T (*lazyupdate)(T, X), X (*lazypropagation)(X, X), X (*rangelazy)(X, int)) : et(Et), ex(Ex), eval(valcal), fa(lazyupdate), fm(lazypropagation), fp(rangelazy) { for (num = 1; num < n; num <<= 1); dat = std::vector (2 * num - 1, et); lazy = std::vector (2 * num - 1, ex); } //update [left,right) void rangeupdate(int left, int right, X val) { std::stack> st; std::stack s; for (st.push({0, num}); !st.empty();) { auto v = st.top(); st.pop(); int now = (num + v.first) / (v.second - v.first) - 1; lazyupdate(now, v.second - v.first); if (left <= v.first && v.second <= right) { lazy[now] = fm(lazy[now], val); lazyupdate(now, v.second - v.first); } else if (!(v.second <= left || right <= v.first)) { st.push({(v.first + v.second) / 2, v.second}); st.push({v.first, (v.first + v.second) / 2}); s.push(now); } } while (!s.empty()) { int index = s.top(); dat[index] = eval(dat[2 * index + 1], dat[2 * index + 2]); s.pop(); } } //get value [left,right) T getval(int left, int right) { std::stack> s; T ans = et; for (s.push({0, num}); !s.empty();) { auto v = s.top(); s.pop(); int now = (num + v.first) / (v.second - v.first) - 1; lazyupdate(now, v.second - v.first); if (left <= v.first && v.second <= right) ans = eval(ans, dat[now]); else if (!(v.second <= left || right <= v.first)) { s.push({(v.first + v.second) / 2, v.second}); s.push({v.first, (v.first + v.second) / 2}); } } return ans; } //get value [id] T getval(int id) {return getval(id, id + 1);} private: void lazyupdate(int index, int len) { if (lazy[index] == ex) return; if (index < num - 1) { lazy[index * 2 + 1] = fm(lazy[index * 2 + 1], lazy[index]); lazy[index * 2 + 2] = fm(lazy[index * 2 + 2], lazy[index]); } dat[index] = fa(dat[index], fp(lazy[index], len)); lazy[index] = ex; } }; int main() { struct dat { int cnt0, cnt1, len; long long sum; dat(int c0, int c1, int l, long long v) : cnt0(c0), cnt1(c1), len(l), sum(v) {} }; auto eval = [](dat a, dat b) -> dat {return dat(a.cnt0 + b.cnt0, a.cnt1 + b.cnt1, a.len + b.len, a.sum + b.sum);}; auto fa = [](dat a, pair b) -> dat { if (b.first) a.sum = a.cnt1; a.sum += b.second * a.len; if (b.second % 2) swap(a.cnt1, a.cnt0); return a; }; auto fm = [](pair a, pair b) -> pair { if (b.first) a.second = 0; a.first |= b.first; a.second += b.second; return a; }; auto fp = [](pair a, int b) -> pair { return a; }; int n, q; cin >> n >> q; vector v; dat e(0, 0, 1, 0); for (int i = 0; i < n; ++i) { int a; cin >> a; v.push_back(dat((a + 1) % 2, a % 2, 1, a)); } LazySegTree> lsg(v, e, {false, 0}, eval, fa, fm, fp); while (q--) { int t; cin >> t; if (t == 1) { int l, r; cin >> l >> r; --l; lsg.rangeupdate(l, r, {true, 0}); } else if (t == 2) { int l, r, x; cin >> l >> r >> x; --l; lsg.rangeupdate(l, r, {false, x}); } else if (t == 3) { int l, r; cin >> l >> r; --l; auto res = lsg.getval(l, r); cout << res.sum << endl; } } }