Submission #697901

#TimeUsernameProblemLanguageResultExecution timeMemory
697901bebraSplit the sequence (APIO14_sequence)C++17
0 / 100
60 ms131072 KiB
#include <bits/stdc++.h> using namespace std; using ll = long long; #define dbg(x) cerr << #x << ": " << x << endl; struct Line { ll k; ll b; Line(ll _k = 0, ll _b = 0) : k(_k), b(_b) {} ll get(ll x) const { return k * x + b; } friend double intersect(const Line& lhs, const Line& rhs) { return (double)(lhs.b - rhs.b) / (rhs.k - lhs.k); } }; struct CHT : vector<Line> { int n; vector<int> indices; CHT() { n = 0; } void add_line(ll k, ll b, int idx) { Line new_line(k, b); // while (n > 0 && back().k == k) { // if (back().b > new_line.b) { // new_line.b = back().b; // idx = indices.back(); // } // --n; // pop_back(); // indices.pop_back(); // } while (n >= 2 && intersect(at(n - 1), at(n - 2)) > intersect(at(n - 2), new_line)) { --n; pop_back(); indices.pop_back(); } ++n; push_back(new_line); indices.push_back(idx); } pair<ll, int> get_max(ll x) { int l = -1; int r = n - 1; while (l != r - 1) { int m = (l + r) / 2; if (intersect(at(m), at(m + 1)) < x) { l = m; } else { r = m; } } return {at(r).get(x), indices[r]}; } }; const int MAX_N = 1e5 + 5; const int MAX_K = 200 + 5; ll dp[MAX_N][MAX_K]; int p[MAX_N][MAX_K]; ll a[MAX_N]; ll pref[MAX_N]; int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int n, k; cin >> n >> k; ll total_sum = 0; for (int i = 1; i <= n; ++i) { cin >> a[i]; pref[i] = pref[i - 1] + a[i]; total_sum += a[i]; } CHT lines; for (int j = 1; j <= k; ++j) { for (int i = 0; i <= n; ++i) { if (i > 0) { tie(dp[i][j], p[i][j]) = lines.get_max(pref[i]); dp[i][j] += pref[i] * (total_sum - pref[i]); } lines.add_line(pref[i], dp[i][j - 1] - pref[i] * total_sum, i); } CHT new_lines; swap(lines, new_lines); } ll ans = 0; int opt = -1; for (int i = 1; i <= n; ++i) { if (dp[i][k] >= ans) { ans = dp[i][k]; opt = i; } } vector<int> splits; int curr_i = opt; int curr_k = k; while (curr_k > 0) { splits.push_back(curr_i); curr_i = p[curr_i][curr_k]; --curr_k; } reverse(splits.begin(), splits.end()); cout << ans << '\n'; for (auto x : splits) { cout << x << ' '; } cout << '\n'; return 0; } /* 7 3 4 1 3 4 0 2 3 */
#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...