Submission #1133491

#TimeUsernameProblemLanguageResultExecution timeMemory
1133491totoroSplit the sequence (APIO14_sequence)C++20
0 / 100
0 ms328 KiB
#include <iostream> #include <vector> #include <utility> const long long INF = 1000000000000000ll; struct ConvexHull { std::vector<std::pair<long long, long long>> lines; std::vector<std::pair<long long, long long>> intervals; // inclusive, line[l] is the GOAT for intervals[l].first..intervals[l].second int ptr = 0; void push(std::pair<long long, long long> line); void emplace(long long m, long long c) {push(std::make_pair(m, c));} long long querymax(long long u, int* sz); }; std::pair<long long, long long> intersect(std::pair<long long, long long> l1, std::pair<long long, long long> l2) { if (l1.first == l2.first) return {INF, INF}; long long left = (l2.second - l1.second) / (l1.first - l2.first); long long right = (l2.second - l1.second - 1) / (l1.first - l2.first) + 1; return {left, right}; } long long apply(std::pair<long long, long long> l, long long u) { return l.first * u + l.second; } void ConvexHull::push(std::pair<long long, long long> line) { if (lines.empty()) { lines.push_back(line); intervals.emplace_back(-INF, INF); } while (lines.size() - ptr >= 2) { auto isct = intersect(line, lines[lines.size()-2]); long long startrange = isct.second; if (startrange < intervals.back().first) { lines.pop_back(); intervals.pop_back(); intervals.back().second = isct.first; } else { break; } } auto isct = intersect(line, lines.back()); lines.push_back(line); intervals.emplace_back(isct.second, INF); } long long ConvexHull::querymax(long long u, int* sz) { while (lines.size() - ptr >= 2) { long long now = apply(lines[ptr], u); long long next = apply(lines[ptr+1], u); if (next > now) ++ptr; else break; } *sz = ptr; return (apply(lines[ptr], u)); } int main() { int n, k; std::cin >> n >> k; std::vector<long long> v(n); for (int i = 0; i < n; ++i) std::cin >> v[i]; std::vector<long long> p(n + 1); for (int i = 1; i <= n; ++i) p[i] = p[i - 1] + v[i - 1]; /* dp[kk][i] is the best value using kk splits with last one 'at' i so if we know dp[kk-1] for all i, then we can calculate dp[kk][i] as: max from prev=0 to prev = i-1 of (dp[kk-1][prev] + (p[i] - p[prev]) * (p.back() - p[i])) now at each kk we define a family of functions f_prev(u) like so: f_prev(u) = dp[kk-1][prev] + p[prev]*u then we can rewrite: dp[kk][i] = (max from family(p[i] - p[back])) + (p[i]*p.back() - p[i]^2) note that for each prev, we have a linear function f_prev */ std::vector<std::vector<long long>> dp(k+2, std::vector<long long>(n+1)); std::vector<std::vector<int>> bestfrom(k+2, std::vector<int>(n+1)); /* when kk=0, it must be that we can get no score */ for (int i = 0; i <= n; ++i) dp[0][i] = 0; /* when i = 0 but kk > 0 then we cannot even do anything, not even score 0 */ for (int kk = 1; kk <= k+1; ++kk) dp[kk][0] = -INF; for (int kk = 1; kk <= k+1; ++kk) { ConvexHull hull; hull.emplace(p[0], dp[kk-1][0]); for (int i = 1; i <= n; ++i) { dp[kk][i] = hull.querymax(p[i] - p.back(), &bestfrom[kk][i]) + p[i] * (p.back() - p[i]); hull.emplace(p[i], dp[kk-1][i]); } } std::cout << dp[k+1][n] << '\n'; int cur = bestfrom[k+1][n]; while (k) { std::cout << cur << " \n"[k==1]; cur = bestfrom[k][cur]; --k; } }
#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...