Submission #1326676

#TimeUsernameProblemLanguageResultExecution timeMemory
1326676hoangtien69Split the sequence (APIO14_sequence)C++20
71 / 100
2099 ms166300 KiB
#include <bits/stdc++.h> using namespace std; #define int long long const int MAXN = 1e5 + 1; const int INF = LLONG_MAX; int n, k; int a[MAXN]; int pre[MAXN], suf[MAXN]; int dp[201][MAXN]; vector<int> trace; struct Line { int a, b; mutable int p; bool operator<(const Line& o) const { if (o.a == LLONG_MAX && o.b == LLONG_MAX) return p < o.p; return a < o.a; } }; struct LineContainer { multiset<Line> s; int divi(int a, int b) { if (b == 0) return (a > 0 ? INF : -INF); int q = a / b; if ((a ^ b) < 0 && a % b) --q; return q; } bool isect(multiset<Line>::iterator x, multiset<Line>::iterator y) { if (y == s.end()) { x->p = INF; return false; } if (x->a == y->a) x->p = (x->b > y->b) ? INF : -INF; else x->p = divi(y->b - x->b, x->a - y->a); return x->p >= y->p; } void add(int a_, int b_) { auto it = s.insert({a_, b_, 0}); auto y = next(it); while (isect(it, y)) y = s.erase(y); if (it != s.begin()) { auto x = it; --x; if (isect(x, it)) isect(x, s.erase(it)); } while (true) { auto y = it; if (y == s.begin()) break; --y; if (y->p < it->p) break; isect(y, s.erase(it)); it = y; } } int query(int x) { Line q{LLONG_MAX, LLONG_MAX, x}; auto it = s.lower_bound(q); if (it == s.end()) --it; return it->a * x + it->b; } bool empty() { return s.empty(); } }; signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n >> k; for (int i = 1; i <= n; ++i) { cin >> a[i]; } for (int i = 1; i <= n; ++i) { pre[i] = pre[i - 1] + a[i]; } for (int i = n; i >= 1; --i) { suf[i] = suf[i + 1] + a[i]; } for (int t = 0; t <= k; ++t) { for (int i = 0; i <= n; ++i) { dp[t][i] = LLONG_MIN; } } for (int i = 1; i <= n-1; ++i) { dp[1][i] = pre[i] * suf[i + 1]; } if (k == 1) { int ans = LLONG_MIN; int point = 0; for (int i = 1; i <= n-1; ++i) { if (ans < dp[1][i]) { ans = dp[1][i]; point = i; } } cout << ans << "\n"; cout << point; return 0; } for (int t = 2; t <= k; ++t) { LineContainer cht; for (int i = t - 1; i <= n - 1; ++i) { if (dp[t-1][i] != LLONG_MIN) { cht.add(-pre[i], dp[t-1][i]); } int nxt = i + 1; if (nxt >= t && nxt <= n - 1 && !cht.empty()) { int cur = cht.query(suf[nxt + 1]); if (cur != LLONG_MIN) { dp[t][nxt] = cur + suf[nxt + 1] * pre[nxt]; } } } } int ans = LLONG_MIN; int point = 0; for (int i = k; i <= n - 1; ++i) { if (ans < dp[k][i]) { ans = dp[k][i]; point = i; } } trace.push_back(point); for (int j = k - 1; j >= 1; j--) { for (int i = 1; i < point; i++) { if (dp[j + 1][point] == dp[j][i] + (pre[point] - pre[i]) * suf[point + 1]) { point = i; trace.push_back(point); break; } } } reverse(trace.begin(), trace.end()); cout << ans << "\n"; for (auto v : trace) { cout << v << " "; } }
#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...