Submission #673252

#TimeUsernameProblemLanguageResultExecution timeMemory
673252CyanmondDischarging (NOI20_discharging)C++17
11 / 100
855 ms227252 KiB
#include <bits/stdc++.h> using i64 = long long; constexpr i64 inf = 1ll << 60; class SparseTable { int n; std::vector<int> log_table; std::vector<std::vector<i64>> data; public: SparseTable(std::vector<i64> vec) : n(vec.size()) { log_table.assign(n + 1, 0); for (int i = 1; i <= n; ++i) { log_table[i] = std::max(log_table[i], log_table[i - 1]); if (2 * i <= n) { log_table[2 * i] = log_table[i] + 1; } } data.resize(log_table[n] + 1); data[0] = vec; for (int d = 1; d <= log_table[n]; ++d) { const int w = 1 << d; data[d].resize(n - w + 1); for (int i = 0; i + w <= n; ++i) { data[d][i] = std::max(data[d - 1][i], data[d - 1][i + w / 2]); } } } i64 fold(int l, int r) const { const int w = r - l; const int d = log_table[w]; return std::max(data[d][l], data[d][r - (1 << d)]); } }; class SegmentTree { int n, size; std::vector<i64> data; public: SegmentTree(int n_) : n(n_) { size = 1; while (size < n) { size *= 2; } data.assign(2 * size, inf); } void set(int i, i64 v) { i += size; data[i] = v; while (i != 1) { i /= 2; data[i] = std::min(data[2 * i], data[2 * i + 1]); } } i64 fold(int l, int r) { i64 ret = inf; for (l += size, r += size; l < r; l /= 2, r /= 2) { if (l % 2 == 0) { ret = std::min(ret, data[l++]); } if (r % 2 == 0) { ret = std::min(ret, data[--r]); } } return ret; } }; class LiChaoTree { struct Line { i64 a, b; i64 get(i64 x) const { return a * x + b; } }; int n, seg_size; std::vector<Line> data; std::stack<std::tuple<int, int, Line, Line>> stk; public: LiChaoTree(int n_) : n(n_) { seg_size = 1; while (seg_size < n) { seg_size *= 2; } data.assign(2 * seg_size, {0, inf}); } void update(int id, const Line &x) { update(id, x, 1, 0, seg_size); } void rollback(int lm) { while (not stk.empty()) { const auto [id, i, pv, nw] = stk.top(); if (lm > id) { break; } stk.pop(); data[i] = pv; } } i64 get(int x) { int xi = x; xi += seg_size; i64 res = inf; while (xi != 0) { res = std::min(res, data[xi].get(x)); xi /= 2; } return res; } private: void update(int id, const Line &x, int k, int l, int r) { const int m = (l + r) / 2; bool l_over = data[k].get(l) > x.get(l), r_over = data[k].get(r - 1) > x.get(r - 1); if (l_over == r_over) { if (l_over) { stk.push({id, k, data[k], x}); data[k] = x; } return; } bool m_over = data[k].get(m) > x.get(m); if (m_over) { stk.push({id, k, data[k], x}); data[k] = x; } if (l_over) { update(id, x, 2 * k, l, m); } if (r_over) { update(id, x, 2 * k + 1, l, r); } } }; int main() { int N; std::cin >> N; std::vector<i64> T(N); for (auto &e : T) { std::cin >> e; } T.push_back(0); std::reverse(T.begin(), T.end()); const auto st = SparseTable(T); SegmentTree dp(N + 1); dp.set(0, 0); LiChaoTree tree(N + 1); tree.update(0, {0, 0}); for (int i = 1; i <= N; ++i) { int l = -1, r = i; while (r - l > 1) { const auto mid = (l + r) / 2; if (st.fold(mid, i) > T[i]) { l = mid; } else { r = mid; } } tree.rollback(r); tree.update(i, {T[i], dp.fold(l == -1 ? 0 : l, i)}); dp.set(i, tree.get(i)); } std::cout << dp.fold(N, N + 1) << std::endl; }
#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...