Submission #869489

#TimeUsernameProblemLanguageResultExecution timeMemory
869489evenvalueTortoise (CEOI21_tortoise)C++17
0 / 100
1 ms612 KiB
#include <bits/stdc++.h> using namespace std; #ifdef evenvalue #include "debug.h" #else #define debug(...) #endif using int64 = long long; using ld = long double; template<typename T> using min_heap = priority_queue<T, vector<T>, greater<T>>; template<typename T> using max_heap = priority_queue<T, vector<T>, less<T>>; namespace read { int Int() { int x; cin >> x; return x; } int64 Int64() { int64 x; cin >> x; return x; } char Char() { char c; cin >> c; return c; } string String() { string s; cin >> s; return s; } double Double() { return stod(String()); } ld LongDouble() { return stold(String()); } template<typename T1, typename T2> pair<T1, T2> Pair() { pair<T1, T2> p; cin >> p.first >> p.second; return p; } template<typename T> vector<T> Vec(const int n) { vector<T> v(n); for (T &x : v) { cin >> x; } return v; } template<typename T> vector<vector<T>> VecVec(const int n, const int m) { vector<vector<T>> v(n); for (vector<T> &vec : v) { vec = Vec<T>(m); } return v; } }//namespace read constexpr int kInf = 1e9 + 10; constexpr int64 kInf64 = 1e15 + 10; constexpr int kMod = 1e9 + 7; constexpr int kMaxN = 2e5 + 10; template<class Node> class LazySegTree { using Unite_t = std::function<Node(const Node &, const Node &)>; using Apply_t = std::function<void(Node &, const Node &)>; using Unlazy = std::function<void(Node &)>; size_t n = 0; std::vector<Node> t; Unite_t unite; Apply_t apply; Unlazy activate; void push(const size_t x, const size_t l, const size_t r) { const size_t mid = (l + r) / 2; const size_t y = 2 * (mid - l + 1) + x; apply(t[x + 1], t[x]); apply(t[y], t[x]); activate(t[x]); } void update(const size_t x, const size_t l, const size_t r, const size_t ql, const size_t qr, const Node upd) { if (ql <= l and r <= qr) { apply(t[x], upd); return; } push(x, l, r); const size_t mid = (l + r) / 2; const size_t y = 2 * (mid - l + 1) + x; if (ql <= mid) { update(x + 1, l, mid, ql, qr, upd); } if (mid < qr) { update(y, mid + 1, r, ql, qr, upd); } t[x] = unite(t[x + 1], t[y]); } Node query(const size_t x, const size_t l, const size_t r, const size_t ql, const size_t qr) { if (ql <= l and r <= qr) { return t[x]; } push(x, l, r); const size_t mid = (l + r) / 2; const size_t y = 2 * (mid - l + 1) + x; if (qr <= mid) { return query(x + 1, l, mid, ql, qr); } else if (mid < ql) { return query(y, mid + 1, r, ql, qr); } else { return unite(query(x + 1, l, mid, ql, qr), query(y, mid + 1, r, ql, qr)); } } void build(const int x, const int l, const int r, const std::vector<Node> &a) { if (l == r) { t[x] = a[l]; return; } const int mid = (l + r) / 2; const int y = 2 * (mid - l + 1) + x; build(x + 1, l, mid, a); build(y, mid + 1, r, a); t[x] = unite(t[x + 1], t[y]); } public: LazySegTree(const size_t n, const Node e, const Unite_t unite, const Apply_t apply, const Unlazy activate) : n(n), t(2 * n - 1, e), unite(unite), apply(apply), activate(activate) {} LazySegTree(const std::vector<Node> &a, const Unite_t unite, const Apply_t apply, const Unlazy activate) : n(a.size()), t(2 * n - 1), unite(unite), apply(apply), activate(activate) { build(0, 0, n - 1, a); } void update(const int ql, const int qr, const Node upd) { assert(0 <= ql and ql <= qr and qr < n); update(0, 0, n - 1, ql, qr, upd); } Node query(const int ql, const int qr) { assert(0 <= ql and ql <= qr and qr < n); return query(0, 0, n - 1, ql, qr); } LazySegTree<Node> &operator=(LazySegTree<Node> other) { swap(n, other.n); swap(t, other.t); swap(unite, other.unite); swap(apply, other.apply); swap(activate, other.activate); return *this; } }; struct candidate { int x; int d; bool operator<(const candidate &other) const { return d < other.d; } }; auto create_segtree(const int n) { struct node { int val = 0; int lazy = 0; }; auto unite = [&](const node &l, const node &r) -> node { return {min(l.val, r.val), 0}; }; auto apply = [&](node &x, const node a) -> void { x.val += a.lazy; x.lazy += a.lazy; }; auto activate = [&](node &x) -> void { x.lazy = 0; }; return LazySegTree<node>(n, node(), unite, apply, activate); } inline void solution() { const int n = read::Int(); vector<int> a = read::Vec<int>(n); vector<int> left(n); left[0] = (a[0] == -1 ? 0 : -kInf); for (int i = 1; i < n; i++) { left[i] = (a[i] == -1 ? i : left[i - 1]); } vector<int> right(n); right[n - 1] = (a[n - 1] == -1 ? n - 1 : kInf); for (int i = n - 2; i >= 0; i--) { right[i] = (a[i] == -1 ? i : right[i + 1]); } vector<int> grp(n); for (int i = 0, g = 0; i < n; i++) { g += (a[i] == -1); grp[i] = g; } vector<int> walk(n); auto st = create_segtree(n + 1); auto increase = [&](const int l, const int r, const int x) { st.update(l, r, {0, x}); }; auto candy_walk = [&](const candidate &c) -> bool { if (c.d < walk[grp[c.x]] or right[c.x] == kInf) return false; const int extra = 2 * walk[grp[c.x]]; const int mn = st.query(c.x, n).val; if (mn < extra) return false; increase(c.x, n, -extra); walk[grp[c.x]] = c.d; return true; }; auto cycle = [&](const candidate &c) -> bool { const int extra = 2 * c.d; const int mn = st.query(c.x, n).val; if (mn < extra) return false; increase(c.x, n, -extra); return true; }; auto purchase = [&](const candidate &c) { const int i = c.x; increase(c.x, c.x, -kInf); int buy = candy_walk(c); if (not buy) increase(c.x, c.x, 2 * c.d); while (a[i] - buy > 0 and st.query(c.x, c.x).val >= 0) { bool complete; complete = cycle(c); buy += complete; if (not complete) break; } if (buy == 0) increase(c.x, c.x, kInf); debug(buy, i); return buy; }; for (int i = 0; i <= n; i++) { increase(i, i, kInf + i); } vector<candidate> candidates; for (int i = 0; i < n; i++) { if (a[i] <= 0) continue; candidate c{}; c.x = i; c.d = min(i - left[i], right[i] - i); candidates.push_back(c); } sort(candidates.begin(), candidates.end()); int ans = 0; for (const candidate c : candidates) { ans -= purchase(c); } for (const int x : a) { if (x == -1) continue; ans += x; } cout << ans << '\n'; } int32_t main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); //freopen(".in", "r", stdin); //freopen(".out", "w", stdout); cout << fixed << setprecision(10); int testcases = 1; //cin >> testcases; while (testcases--) { solution(); } }

Compilation message (stderr)

In file included from /usr/include/c++/10/cassert:44,
                 from /usr/include/x86_64-linux-gnu/c++/10/bits/stdc++.h:33,
                 from tortoise.cpp:1:
tortoise.cpp: In instantiation of 'void LazySegTree<Node>::update(int, int, Node) [with Node = create_segtree(int)::node]':
tortoise.cpp:227:27:   required from here
tortoise.cpp:150:40: warning: comparison of integer expressions of different signedness: 'const int' and 'size_t' {aka 'long unsigned int'} [-Wsign-compare]
  150 |     assert(0 <= ql and ql <= qr and qr < n);
      |                                     ~~~^~~
tortoise.cpp: In instantiation of 'Node LazySegTree<Node>::query(int, int) [with Node = create_segtree(int)::node]':
tortoise.cpp:233:35:   required from here
tortoise.cpp:155:40: warning: comparison of integer expressions of different signedness: 'const int' and 'size_t' {aka 'long unsigned int'} [-Wsign-compare]
  155 |     assert(0 <= ql and ql <= qr and qr < n);
      |                                     ~~~^~~
#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...