#include #include #include #include #include #define FAST_ALLOCATOR_MEMORY (230*1024*1024) #include "optimization.h" using namespace std; using ll = long long; template struct Monoid; template struct ValidMonoid : private Mon { using value_type = typename Mon::value_type; using T = typename Mon::value_type; static_assert(std::is_same_v(), std::declval())), T>); static_assert(std::is_same_v); using Mon::compose; using Mon::identity; }; template struct Updater : Updater> { using valid = ValidMonoid>; }; template struct ValidUpdater : private Upd { using value_type = typename Upd::value_type; using update_type = typename Upd::update_type; using T = typename Upd::value_type; using U = typename Upd::update_type; using valid = ValidMonoid; static_assert(std::is_same_v(), std::declval(), std::declval(), std::declval())), T>); using Upd::update; using Upd::compose; using Upd::identity; }; template struct Updater> : Monoid { using M = Monoid; using valid = ValidMonoid; using value_type = typename M::value_type; using update_type = typename M::value_type; static value_type update(const value_type& a, const update_type& b, size_t l, size_t r) { return M::compose(a, b); } }; template struct STOp { using composer = ValidMonoid>; using updater = ValidUpdater>; }; template struct ValidSTOp : Op { using compose_valid = ValidMonoid; using updater_valid = ValidUpdater; static_assert(std::is_same_v); using typename Op::composer; using typename Op::updater; }; template class SegmentTree { public: using Op = ValidSTOp>; using Cm = ValidMonoid; using Up = ValidUpdater; using T = typename Cm::value_type; using U = typename Up::update_type; explicit SegmentTree(size_t n) : n(n) { data.resize(4 * n, Cm::identity()); updates.resize(data.size(), Up::identity()); } explicit SegmentTree(int n) : SegmentTree(static_cast(n)) {} template explicit SegmentTree(const Cont& cont) : SegmentTree(cont.size()) { build(cont, 1, 0, n); } T compute(size_t l, size_t r) { return compute(1, 0, n, l, r); } void applyToLeaf(size_t i, std::function f) { applyToLeaf(1, 0, n, i, std::move(f)); } void applyToLeaf(size_t i, std::function f) { applyToLeaf(i, [f](const T& t, size_t l, size_t r){ return f(t); }); } void set(size_t i, T x) { applyToLeaf(i, [&x](const T& y, size_t l, size_t r) { return x; }); } void update(size_t i, U upd) { applyToLeaf(i, [this, &upd](const T& x, size_t l, size_t r) { return Up::update(x, upd, l, r); }); } void update(size_t l, size_t r, U upd) { update(1, 0, n, l, r, upd); } private: void check_bounds(size_t v, size_t vl, size_t vr, size_t l, size_t r) { assert(v < data.size()); assert(vl <= n); assert(vr <= n); assert(l <= n); assert(r <= n); } T compute(size_t v, size_t vl, size_t vr, size_t l, size_t r) { check_bounds(v, vl, vr, l, r); if (disjoint(vl, vr, l, r)) return Cm::identity(); if (embedded(vl, vr, l, r)) { return data[v]; } size_t vm = mid(vl, vr); return Up::update( Cm::compose( compute(left(v), vl, vm, l, r), compute(right(v), vm, vr, l, r) ), updates[v], vl, vr ); } void update(size_t v, size_t vl, size_t vr, size_t l, size_t r, U upd) { check_bounds(v, vl, vr, l, r); recompute(v, vl, vr); if (disjoint(vl, vr, l, r)) return; if (embedded(vl, vr, l, r)) { updates[v] = Up::compose(updates[v], upd); recompute(v, vl, vr); return; } size_t vm = mid(vl, vr); push(v); update(left(v), vl, vm, l, r, upd); update(right(v), vm, vr, l, r, upd); recompute(v, vl, vr); } void push(size_t v) { assert(v < data.size()); updates[left(v)] = Up::compose(updates[left(v)], updates[v]); updates[right(v)] = Up::compose(updates[right(v)], updates[v]); updates[v] = Up::identity(); } void applyToLeaf(size_t v, size_t vl, size_t vr, size_t i, std::function f) { check_bounds(v, vl, vr, 0, 0); if (vl == i && vr == i + 1) { data[v] = f(data[v], vl, vr); return; } size_t vm = mid(vl, vr); if (i < vm) applyToLeaf(left(v), vl, vm, i, f); else applyToLeaf(right(v), vm, vr, i, f); recompute(v, vl, vr); } template void build(const Cont& cnt, size_t v, size_t vl, size_t vr) { if(vl + 1 == vr) { data[v] = cnt[vl]; return; } size_t vm = mid(vl, vr); build(cnt, left(v), vl, vm); build(cnt, right(v), vm, vr); recompute(v, vl, vr); } bool disjoint(size_t vl, size_t vr, size_t l, size_t r) { return vr <= l || r <= vl; } bool embedded(size_t vl, size_t vr, size_t l, size_t r) { return l <= vl && vr <= r; } size_t mid(size_t vl, size_t vr) { return (vl + vr + 1) / 2; } size_t left(size_t i) { return 2 * i; } size_t right(size_t i) { return 2 * i + 1; } void recompute(size_t i, size_t vl, size_t vr) { check_bounds(i, vl, vr, 0, 0); if(vl + 1 == vr) { data[i] = Up::update(data[i], updates[i], vl, vr); updates[i] = Up::identity(); } else { data[i] = Up::update( Cm::compose(data[left(i)], data[right(i)]), updates[i], vl, vr ); } } size_t n; std::vector data; std::vector updates; }; template struct Sum { }; template struct Monoid> { using value_type = T; static T identity() { return id; }; static T compose(T a, T b) { return a + b; } }; template struct Updater> : Monoid> { using update_type = T; static T update(T x, T up, size_t l, size_t r) { return x + up * (r - l); } }; template::max()> struct Min { }; template struct Monoid> { using value_type = T; static T identity() { return id; }; static T compose(T a, T b) { return min(a, b); } }; template::min()> struct Max { }; template struct Monoid> { using value_type = T; static T identity() { return *id; }; static T compose(T a, T b) { return max(a, b); } }; //template //struct Updater> : Monoid> { // // using value_type = T; // using update_type = T; // // static value_type update(value_type a, update_type b, size_t l, size_t r) { // return max(a, b); // } // //}; template struct PureSum { }; template struct Updater> : Monoid> { using update_type = T; static T update(const T& a, const T& b, size_t l, size_t r) { return a + b; } }; struct CountSegments {}; struct CSNode { enum class Color { BLACK, WHITE }; Color beg, end; size_t black_cnt, len; }; std::string to_str(CSNode::Color c) { return c == CSNode::Color::BLACK ? "B" : "W"; } bool debug = false; template<> struct Monoid { using value_type = CSNode; using Color = CSNode::Color; static value_type identity() { return {Color::WHITE, Color::WHITE, 0, 0}; } static value_type compose(value_type a, value_type b) { CSNode res = {a.beg, b.end, a.black_cnt + b.black_cnt - (a.end == Color::BLACK && b.beg == Color::BLACK), a.len + b.len}; if(debug) std::cerr << "Composing " << to_str(a.beg) << "[" << a.black_cnt << "]" << to_str(a.end) << " with " << to_str(b.beg) << "[" << b.black_cnt << "]" << to_str(b.end) << " result " << to_str(res.beg) << "[" << res.black_cnt << "]" << to_str(res.end) << std::endl; return res; } }; template<> struct Updater { using value_type = CSNode; using update_type = std::optional; static update_type identity() { return std::optional(); } static update_type compose(update_type a, update_type b) { if(!b.has_value()) return a; return b; } static value_type update(value_type a, update_type u, size_t l, size_t r) { if(!u.has_value()) return a; CSNode res = {u.value(), u.value(), u.value() == CSNode::Color::BLACK, u.value() == CSNode::Color::BLACK ? (r - l) : 0}; if(debug) std::cerr << "Updating " << to_str(a.beg) << "[" << a.black_cnt << "]" << to_str(a.end) << " to " << to_str(res.beg) << "[" << res.black_cnt << "]" << to_str(res.end) << std::endl; return res; } }; struct RectUpdater; template<> struct Updater : Monoid> { using value_type = pair; using update_type = int; static value_type update(value_type rect, update_type k, size_t l, size_t r) { return {rect.first + k, rect.second}; } }; struct CountDisting {}; template<> struct Monoid { using value_type = set; static value_type identity() { return set(); } static value_type compose(value_type a, value_type b) { set res; res.insert(a.begin(), a.end()); res.insert(b.begin(), b.end()); return res; } }; template struct NoUpdates {}; template struct Updater> { using value_type = T; using update_type = char; static update_type identity() { return 0; } static update_type compose(update_type a, update_type b) { return 0; } static value_type update(value_type a, update_type b, size_t l, size_t r) { return a; } }; template struct ComplexOp { }; template struct STOp> { using composer = ValidMonoid::composer>; using updater = ValidUpdater::updater>; }; using sum_type = size_t; constexpr pair identity{0, -1}; int main() { int n = readInt(); std::vector> data; data.reserve(n); for (int i = 0; i < n; ++i) { data.push_back(set{readInt()}); } SegmentTree>>> tree(data); int k = readInt(); std::vector> events; for (int i = 0; i < k; ++i) { int l = readInt(), r = readInt(); writeInt(tree.compute(l - 1, r).size(), '\n'); } } //int main() { // int n = readInt(); // std::vector> events; // for (int i = 0; i < n; ++i) { // int x1 = readInt(), y1 = readInt(), x2 = readInt(), y2 = readInt(), k = readInt(); // events.emplace_back(x1, 0, y1, y2, k, i); // events.emplace_back(x2, 2, y1, y2, k, i); // } // sort(events.begin(), events.end()); // std::vector coords{(int) -2e9, (int) 2e9}; // for (auto [x, type, y1, y2, k, i] : events) { // coords.push_back(y1 - 1); // coords.push_back(y1 * 1); // coords.push_back(y2 * 1); // } // sort(coords.begin(), coords.end()); // coords.erase(unique(coords.begin(), coords.end()), coords.end()); // std::vector> rects(n); // size_t N = coords.size(); // SegmentTree, &identity>> tree(N); // for(auto [x, type, y1, y2, k, i] : events) { // y1 = lower_bound(coords.begin(), coords.end(), y1) - coords.begin(); // y2 = lower_bound(coords.begin(), coords.end(), y2) - coords.begin(); // switch(type) { // case 0: { // rects[i] = tree.compute(y2, N); //y2_new < y1_old // rects[i].first += k; // break; // } // case 2: { // tree.update(y1 - 1, y1, {rects[i].first, i}); // break; // } // } // } // int maxI = 0; // for (int i = 0; i < n; ++i) { // if(rects[i].first > rects[maxI].first) { // maxI = i; // } // } // std::vector chain; // for(int i = maxI; i != -1; i = rects[i].second) { // chain.push_back(i); // } // std::reverse(chain.begin(), chain.end()); // writeInt(rects[maxI].first, '\n'); // for(int i : chain) { // writeInt(i + 1, ' '); // } // writeChar('\n'); //} // x1 y1 x2 y2 // a1 b1 a2 b2 // a1 > x2 && b2 < y1 //WWWWWWWWWWW //WWWWWWWWWWW //WWBBWWWWWWW //WWBBBBWWWWW //WWBBBBWWWWW //WWBBBBWBBWW //WWBWBBWBBWW //WWWWWWWWWWW //int main() { // int n = readInt(); // int N = 1000002; // SegmentTree tree(N); // for (int i = 0; i < n; ++i) { // debug = i == 5; // int color = readChar(), x = readInt(), l = readInt(); // x += 500000; // tree.update(x, x+l, color == 'W' ? CSNode::Color::WHITE : CSNode::Color::BLACK); // CSNode ans = tree.compute(0, N); // writeInt(ans.black_cnt, ' '); // writeInt(ans.len, '\n'); // } //} //int main() { // int n = readInt(), q = readInt(); // vector v; // v.reserve(n); // for (int i = 0; i < n; ++i) { // v.push_back(readInt()); // } // SegmentTree(-1e15)>, PureSum>> tree(v); // for (int i = 0; i < q; ++i) { // int cmd = readChar(); // readChar(); // readChar(); // int l = readInt() - 1, r = readInt(); // if (cmd == 'm') { // writeInt(tree.compute(l, r), '\n'); // } else { // int x = readInt(); // tree.update(l, r, x); // } // } // return 0; //}