Submission #689583

#TimeUsernameProblemLanguageResultExecution timeMemory
689583CyanmondFish 2 (JOI22_fish2)C++17
100 / 100
1740 ms21444 KiB
#include <bits/stdc++.h> using i64 = long long; constexpr i64 inf64 = 1ll << 50; constexpr int inf = 1000000000; template <class M> class segTree { int n, size; using T = typename M::T; std::vector<T> data; void update(int i) { data[i] = M::op(data[2 * i], data[2 * i + 1]); } public: segTree(int n_) : n(n_) { size = 1; while (size < n) { size *= 2; } data.assign(2 * size, M::id()); } void set(int i, T v) { i += size; data[i] = v; while (i != 1) { i /= 2; update(i); } } T fold(int l, int r) { T pl = M::id(), pr = M::id(); for (l += size, r += size; l < r; l /= 2, r /= 2) { if (l % 2 == 1) { pl = M::op(pl, data[l++]); } if (r % 2 == 1) { pr = M::op(data[--r], pr); } } return M::op(pl, pr); } template <class F> int maxRight(int l, F f) { assert(f(M::id())); if (l == n) { return n; } l += size; T p = M::id(); do { while (l % 2 == 0) { l /= 2; } if (not f(M::op(p, data[l]))) { while (l < size) { l *= 2; if (f(M::op(p, data[l]))) { p = M::op(p, data[l]); ++l; } } return l - size; } p = M::op(p, data[l]); ++l; } while ((l & (-l)) != l); return n; } template <class F> int minLeft(int r, F f) { assert(f(M::id())); if (r == 0) { return 0; } r += size; T p = M::id(); do { --r; while (r > 1 and (r % 2 == 1)) { r /= 2; } if (not f(M::op(data[r], p))) { while (r < size) { r = 2 * r + 1; if (f(M::op(data[r], p))) { p = M::op(data[r], p); --r; } } return r + 1 - size; } } while ((r & (-r)) != r); return 0; } }; constexpr int B = 1000; struct rangeSum64 { using T = i64; static T op(T a, T b) { return a + b; } static T id() { return 0; } }; struct rangeMax64 { using T = i64; static T op(T a, T b) { return std::max(a, b); } static T id() { return -inf64; } }; struct rangeMaxWithIndex32 { using T = std::pair<int, int>; static T op(T a, T b) { return std::max(a, b); } static T id() { return {-inf, 0}; } }; struct rangeSum32 { using T = int; static T op(T a, T b) { return a + b; } static T id() { return 0; } }; struct rangeMax32 { using T = int; static T op(T a, T b) { return std::max(a, b); } static T id() { return -inf; } }; int main() { // input int N; std::cin >> N; std::vector<i64> A(N); for (auto &e : A) { std::cin >> e; } segTree<rangeSum64> sumA(N); segTree<rangeMax64> maxA(N); for (int i = 0; i < N; ++i) { sumA.set(i, A[i]); maxA.set(i, A[i]); } segTree<rangeMaxWithIndex32> maxR(N); auto expandRange = [&](int &l, int &r) { while (true) { const auto sum = sumA.fold(l, r); const auto limitL = maxA.minLeft(l, [&](const auto v) { return v <= sum; }); const auto limitR = maxA.maxRight(r, [&](const auto v) { return v <= sum; }); const auto newL = limitL, newR = limitR; if (l == newL and r == newR) { break; } l = newL; r = newR; } }; auto findRanges = [&](const int m, auto f) { int l = m, r = m + 1; while (true) { expandRange(l, r); if (l == 0 and r == N) { break; } f(l, r); if (l == 0) { ++r; continue; } if (r == N) { --l; continue; } if (A[l - 1] < A[r]) { --l; } else { ++r; } } }; auto eraseRanges = [&](const int m, auto f) { while (true) { const auto [ma, i] = maxR.fold(0, m + 1); if (ma <= m) { break; } f(i, ma); } }; std::vector<std::set<int>> rangesEachL(N); std::vector<int> countShortRanges(N); segTree<rangeSum32> sumPoints(N); segTree<rangeMax32> maxLargeRangesR(N); for (int i = 0; i < N; ++i) { sumPoints.set(i, 1); } auto addPoint = [&](const int i, const int d) { assert(d == 1 or d == -1); if (countShortRanges[i] == 0 and d == 1) { sumPoints.set(i, 0); } if (countShortRanges[i] == 1 and d == -1) { sumPoints.set(i, 1); } countShortRanges[i] += d; assert(0 <= countShortRanges[i]); }; auto applyAddRange = [&](int l, int r) { if (rangesEachL[l].find(r) != rangesEachL[l].end()) { return; } rangesEachL[l].insert(r); maxR.set(l, {rangesEachL[l].empty() ? -inf : *rangesEachL[l].rbegin(), l}); if (r - l < B) { for (int i = l; i < r; ++i) { addPoint(i, 1); } } else { maxLargeRangesR.set(l, *rangesEachL[l].rbegin()); } }; auto applyEraseRange = [&](int l, int r) { assert(rangesEachL[l].find(r) != rangesEachL[l].end()); rangesEachL[l].erase(r); maxR.set(l, {rangesEachL[l].empty() ? -inf : *rangesEachL[l].rbegin(), l}); if (r - l < B) { for (int i = l; i < r; ++i) { addPoint(i, -1); } } else { if (not rangesEachL[l].empty()) { const auto v = *rangesEachL[l].rbegin(); if (v - l >= B) { maxLargeRangesR.set(l, v); } else { maxLargeRangesR.set(l, -inf); } } else { maxLargeRangesR.set(l, -inf); } } }; for (int i = 0; i < N; ++i) { findRanges(i, applyAddRange); } // answer queries int Q; std::cin >> Q; while (Q--) { int t; std::cin >> t; if (t == 1) { int x; i64 y; std::cin >> x >> y; --x; A[x] = y; sumA.set(x, y); maxA.set(x, y); eraseRanges(x, applyEraseRange); if (x != 0) { eraseRanges(x - 1, applyEraseRange); } if (x != N - 1) { eraseRanges(x + 1, applyEraseRange); } findRanges(x, applyAddRange); if (x != 0) { findRanges(x - 1, applyAddRange); } if (x != N - 1) { findRanges(x + 1, applyAddRange); } } if (t == 2) { int l, r; std::cin >> l >> r; --l; // find true l and r i64 memo = -1; int realL = l; if (l != 0) { memo = A[l - 1]; A[l - 1] = inf64; sumA.set(l - 1, A[l - 1]); maxA.set(l - 1, A[l - 1]); } findRanges(l, [&](int a, int b) { assert(a == l); if (b < r) { realL = b; } }); if (l != 0) { A[l - 1] = memo; sumA.set(l - 1, A[l - 1]); maxA.set(l - 1, A[l - 1]); } int realR = r; if (r != N) { memo = A[r]; A[r] = inf64; sumA.set(r, A[r]); maxA.set(r, A[r]); } findRanges(r - 1, [&](int a, int b) { assert(b == r); if (a > l) { realR = a; } }); if (r != N) { A[r] = memo; sumA.set(r, A[r]); maxA.set(r, A[r]); } assert(realL < realR); if (r - l < B) { std::vector<int> imos(r - l + 1); auto itr = rangesEachL[l].lower_bound(r); if (itr != rangesEachL[l].begin()) { --itr; ++imos[0]; --imos[*itr - l]; } for (int i = l + 1; i < r; ++i) { if (rangesEachL[i].empty()) { continue; } auto avalR = rangesEachL[i].rbegin(); ++imos[i - l]; --imos[std::min(r, *avalR) - l]; } int answer = 0; for (int i = 0; i < r - l; ++i) { if (realL <= i + l and i + l < realR and imos[i] == 0) { ++answer; } imos[i + 1] += imos[i]; } std::cout << answer << std::endl; continue; } int answer = 0; auto itr = rangesEachL[l].lower_bound(r); int nowR = realL; if (realL == l) { if (countShortRanges[l] == 0) { ++answer; } ++nowR; } while (nowR < realR) { const auto nextR = maxLargeRangesR.fold(l + 1, nowR + 1); if (nextR > nowR) { nowR = nextR; } else { // problem... const auto nextStep = maxLargeRangesR.maxRight(nowR, [&](const auto v) { return v <= nowR; }); answer += sumPoints.fold(nowR, std::min(realR, nextStep)); nowR = nextStep; } } std::cout << answer << std::endl; } } }

Compilation message (stderr)

fish2.cpp: In function 'int main()':
fish2.cpp:410:18: warning: variable 'itr' set but not used [-Wunused-but-set-variable]
  410 |             auto itr = rangesEachL[l].lower_bound(r);
      |                  ^~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...