結果
問題 | No.879 Range Mod 2 Query |
ユーザー | noshi91 |
提出日時 | 2019-09-06 21:46:50 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 289 ms / 3,000 ms |
コード長 | 12,720 bytes |
コンパイル時間 | 769 ms |
コンパイル使用メモリ | 78,128 KB |
実行使用メモリ | 13,568 KB |
最終ジャッジ日時 | 2024-06-24 22:06:33 |
合計ジャッジ時間 | 4,777 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 3 ms
5,376 KB |
testcase_02 | AC | 4 ms
5,376 KB |
testcase_03 | AC | 4 ms
5,376 KB |
testcase_04 | AC | 3 ms
5,376 KB |
testcase_05 | AC | 3 ms
5,376 KB |
testcase_06 | AC | 2 ms
5,376 KB |
testcase_07 | AC | 4 ms
5,376 KB |
testcase_08 | AC | 3 ms
5,376 KB |
testcase_09 | AC | 3 ms
5,376 KB |
testcase_10 | AC | 3 ms
5,376 KB |
testcase_11 | AC | 279 ms
13,440 KB |
testcase_12 | AC | 179 ms
13,440 KB |
testcase_13 | AC | 211 ms
13,440 KB |
testcase_14 | AC | 201 ms
13,568 KB |
testcase_15 | AC | 195 ms
8,320 KB |
testcase_16 | AC | 284 ms
13,440 KB |
testcase_17 | AC | 281 ms
13,440 KB |
testcase_18 | AC | 289 ms
13,440 KB |
testcase_19 | AC | 277 ms
13,440 KB |
testcase_20 | AC | 275 ms
13,440 KB |
testcase_21 | AC | 288 ms
13,440 KB |
ソースコード
//#define NDEBUG #include <cstddef> #include <cstdint> #include <iostream> #include <vector> namespace n91 { using i8 = std::int_fast8_t; using i32 = std::int_fast32_t; using i64 = std::int_fast64_t; using u8 = std::uint_fast8_t; using u32 = std::uint_fast32_t; using u64 = std::uint_fast64_t; using isize = std::ptrdiff_t; using usize = std::size_t; constexpr usize operator"" _z(unsigned long long x) noexcept { return static_cast<usize>(x); } class rep { const usize f, l; public: class itr { friend rep; usize i; constexpr itr(const usize x) noexcept : i(x) {} public: void operator++() noexcept { ++i; } constexpr usize operator*() const noexcept { return i; } constexpr bool operator!=(const itr x) const noexcept { return i != x.i; } }; constexpr rep(const usize first, const usize last) noexcept : f(first), l(last) {} constexpr itr begin() const noexcept { return itr(f); } constexpr itr end() const noexcept { return itr(l); } }; class revrep { const usize f, l; public: class itr { friend revrep; usize i; constexpr itr(usize x) noexcept : i(x) {} public: void operator++() noexcept { --i; } constexpr usize operator*() const noexcept { return i; } constexpr bool operator!=(const itr x) const noexcept { return i != x.i; } }; constexpr revrep(usize first, usize last) noexcept : f(--first), l(--last) {} constexpr itr begin() const noexcept { return itr(l); } constexpr itr end() const noexcept { return itr(f); } }; template <class T> using vec_alias = std::vector<T>; template <class T> auto md_vec(const usize n, const T& value) { return std::vector<T>(n, value); } template <class... Args> auto md_vec(const usize n, Args... args) { return std::vector<decltype(md_vec(args...))>(n, md_vec(args...)); } template <class T> constexpr T difference(const T& a, const T& b) { return a < b ? b - a : a - b; } template <class T> T scan() { T ret; std::cin >> ret; return ret; } } // namespace n91 #include <cassert> #include <iterator> #include <utility> #include <vector> template <class Monoid> class segment_tree { public: using value_structure = Monoid; using value_type = typename value_structure::value_type; using container_type = std::vector<value_type>; using const_reference = typename container_type::const_reference; using size_type = typename container_type::size_type; protected: static size_type getsize(const size_type size) { size_type ret = 1; while (ret < size) ret <<= 1; return ret; } size_type size_; container_type tree; size_type base_size() const { return tree.size() >> 1; } void recalc(const size_type index) { tree[index] = value_structure::operation(tree[index << 1], tree[index << 1 | 1]); } public: segment_tree() : size_(0), tree() {} explicit segment_tree(const size_type size) : size_(size), tree(getsize(size) << 1, value_structure::identity()) {} template <class InputIterator> segment_tree(InputIterator first, InputIterator last) : size_(::std::distance(first, last)), tree() { const size_type cap = getsize(size_); tree.reserve(cap << 1); tree.resize(cap, value_structure::identity()); tree.insert(tree.end(), first, last); tree.resize(cap << 1, value_structure::identity()); for (size_type i = cap - 1; i; --i) recalc(i); } bool empty() const { return !size_; } size_type size() const { return size_; } const_reference operator[](const size_type index) const { assert(index < size()); return tree[index + base_size()]; } value_type fold(size_type first, size_type last) const { assert(first <= last); assert(first <= size()); assert(last <= size()); value_type ret_l = value_structure::identity(), ret_r = value_structure::identity(); for (first += base_size(), last += base_size(); first < last; first >>= 1, last >>= 1) { if (first & 1) ret_l = value_structure::operation(::std::move(ret_l), tree[first++]); if (last & 1) ret_r = value_structure::operation(tree[last - 1], ::std::move(ret_r)); } return value_structure::operation(::std::move(ret_l), ::std::move(ret_r)); } template <class F> size_type search(const F& f) const { if (f(value_structure::identity())) return 0; if (!f(tree[1])) return size() + 1; value_type acc = value_structure::identity(); size_type i = 1; while (i < base_size()) if (!f(value_structure::operation(acc, tree[i <<= 1]))) acc = value_structure::operation(::std::move(acc), tree[i++]); return i - base_size() + 1; } template <class F> void update(size_type index, const F& f) { assert(index < size()); index += base_size(); tree[index] = f(::std::move(tree[index])); while (index >>= 1) recalc(index); } }; #include <cassert> #include <iterator> #include <stdexcept> #include <utility> template <class ValueMonoid, class OperatorMonoid, class Modifier, template <class> class Container> class lazy_segment_tree { public: using value_structure = ValueMonoid; using value_type = typename value_structure::value_type; using const_reference = const value_type &; using operator_structure = OperatorMonoid; using operator_type = typename operator_structure::value_type; using modifier = Modifier; using container_type = Container<::std::pair<value_type, operator_type>>; using size_type = typename container_type::size_type; private: size_type size_, height; container_type tree; static size_type getheight(const size_type size) noexcept { size_type ret = 0; while (static_cast<size_type>(1) << ret < size) ++ret; return ret; } static value_type reflect(typename container_type::const_reference element) { return modifier::operation(element.first, element.second); } void recalc(const size_type index) { tree[index].first = value_structure::operation( reflect(tree[index << 1]), reflect(tree[index << 1 | 1])); } static void assign(operator_type& element, const operator_type& data) { element = operator_structure::operation(element, data); } void push(const size_type index) { assign(tree[index << 1].second, tree[index].second); assign(tree[index << 1 | 1].second, tree[index].second); tree[index].second = operator_structure::identity(); } void propagate(const size_type index) { for (size_type i = height; i; --i) push(index >> i); } void thrust(const size_type index) { tree[index].first = reflect(tree[index]); push(index); } void evaluate(const size_type index) { for (size_type i = height; i; --i) thrust(index >> i); } void build(size_type index) { while (index >>= 1) recalc(index); } size_type base_size() const { return static_cast<size_type>(1) << height; } public: lazy_segment_tree() : size_(0), height(0), tree() {} explicit lazy_segment_tree(const size_type size) : size_(size), height(getheight(size_)), tree(static_cast<size_type>(1) << (height + 1), { value_structure::identity(), operator_structure::identity() }) {} template <class InputIterator> explicit lazy_segment_tree(InputIterator first, InputIterator last) : size_(::std::distance(first, last)), height(getheight(size_)), tree() { const size_type cap = static_cast<size_type>(1) << height; tree.reserve(cap << 1); tree.resize(cap, { value_structure::identity(), operator_structure::identity() }); for (; first != last; ++first) tree.emplace_back(*first, operator_structure::identity()); tree.resize(cap << 1, { value_structure::identity(), operator_structure::identity() }); for (size_type i = cap - 1; i; --i) recalc(i); } bool empty() const { return !size_; } size_type size() const { return size_; } const_reference operator[](size_type index) { assert(index < size()); index += base_size(); evaluate(index); tree[index].first = reflect(tree[index]); tree[index].second = operator_structure::identity(); return tree[index].first; } const_reference at(size_type index) { if (index < size()) { throw ::std::out_of_range("index out of range"); } else { index += base_size(); evaluate(index); tree[index].first = reflect(tree[index]); tree[index].second = operator_structure::identity(); return tree[index].first; } } value_type fold(size_type first, size_type last) { assert(first <= last); assert(first <= size()); assert(last <= size()); first += base_size(); last += base_size(); evaluate(first); evaluate(last - 1); value_type ret_l = value_structure::identity(), ret_r = value_structure::identity(); for (; first < last; first >>= 1, last >>= 1) { if (first & 1) ret_l = value_structure::operation(ret_l, reflect(tree[first++])); if (last & 1) ret_r = value_structure::operation(reflect(tree[last - 1]), ret_r); } return value_structure::operation(ret_l, ret_r); } template <class F> size_type search(const F& f) { if (f(value_structure::identity())) return static_cast<size_type>(0); if (!f(reflect(tree[1]))) return size() + 1; value_type acc = value_structure::identity(); size_type i = 1; while (i < base_size()) { thrust(i); if (!f(value_structure::operation(acc, reflect(tree[i <<= 1])))) acc = value_structure::operation(acc, reflect(tree[i++])); } return i - base_size() + 1; } template <class F> void update(size_type index, const F& f) { assert(index < size()); index += base_size(); propagate(index); tree[index].first = f(reflect(tree[index])); tree[index].second = operator_structure::identity(); build(index); } void update(size_type first, size_type last, const operator_type& data) { assert(first <= last); assert(first <= size()); assert(last <= size()); first += base_size(); last += base_size(); propagate(first); propagate(last - 1); for (size_type left = first, right = last; left < right; left >>= 1, right >>= 1) { if (left & 1) assign(tree[left++].second, data); if (right & 1) assign(tree[right - 1].second, data); } build(first); build(last - 1); } }; template <class T> using vec_alias = std::vector<T>; #include <algorithm> #include <iostream> #include <utility> namespace n91 { struct ushi { u64 sum; u64 eve, odd; }; struct beet { bool flip; bool comp; u64 add; }; struct uop { using value_type = ushi; static ushi operation(const ushi& l, const ushi& r) { return ushi({ l.sum + r.sum, l.eve + r.eve, l.odd + r.odd }); } static ushi identity() { return ushi({ 0, 0, 0 }); } }; struct bop { using value_type = beet; static beet operation(beet l, const beet& r) { if (r.comp) { l.comp = true; if (l.add % 2 == 1) { l.flip = !l.flip; } if (r.flip) { l.flip = !l.flip; } l.add = r.add; } else { l.add += r.add; } return l; } static beet identity() { return beet({ false, false, 0 }); } }; struct op { static ushi operation(ushi u, const beet& b) { if (b.comp) { if (b.flip) { std::swap(u.odd, u.eve); } u.sum = u.eve; } u.sum += b.add * (u.eve + u.odd); if (b.add % 2 == 1) { std::swap(u.odd, u.eve); } return u; } }; void main_() { const usize n = scan<usize>(); const usize q = scan<usize>(); lazy_segment_tree<uop, bop, op, vec_alias> lsg(n); for (const auto i : rep(0_z, n)) { const u64 a = scan<u64>(); lsg.update(i, [a](auto) { return ushi({ a, a % 2, (a + 1) % 2 }); }); } for (const auto i : rep(0_z, q)) { u32 t; std::cin >> t; if (t == 1) { const usize l = scan<usize>() - 1; const usize r = scan<usize>(); lsg.update(l, r, beet({ false, true, 0 })); } else if (t == 2) { const usize l = scan<usize>() - 1; const usize r = scan<usize>(); const u64 x = scan<u64>(); lsg.update(l, r, beet({ false, false, x })); } else { const usize l = scan<usize>() - 1; const usize r = scan<usize>(); std::cout << lsg.fold(l, r).sum << std::endl; } } } } // namespace n91 int main() { n91::main_(); return 0; }