#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = LLONG_MAX/4;
int n, K;
vector<ll> a;
vector<vector<ll>> stMax;
vector<int> log2v;
// Precompute sparse table for RMQ max
void buildSparse() {
log2v.assign(n+2, 0);
for (int i = 2; i <= n; i++) log2v[i] = log2v[i/2] + 1;
int maxLog = log2v[n];
stMax.assign(maxLog+1, vector<ll>(n+1));
for (int i = 1; i <= n; i++) stMax[0][i] = a[i];
for (int k = 1; k <= maxLog; k++) {
for (int i = 1; i + (1<<k) - 1 <= n; i++) {
stMax[k][i] = max(stMax[k-1][i], stMax[k-1][i + (1<<(k-1))]);
}
}
}
// Query max in a[l..r]
ll queryMax(int l, int r) {
if (l > r) return 0;
int len = r - l + 1;
int k = log2v[len];
return max(stMax[k][l], stMax[k][r - (1<<k) + 1]);
}
vector<ll> dp_prev, dp_cur;
void compute(int k, int L, int R, int optL, int optR) {
if (L > R) return;
int mid = (L + R) >> 1;
ll bestVal = INF;
int bestPos = -1;
int start = max(k-1, optL);
int end = min(mid-1, optR);
for (int j = start; j <= end; j++) {
ll val = dp_prev[j] + queryMax(j+1, mid);
if (val < bestVal) {
bestVal = val;
bestPos = j;
}
}
dp_cur[mid] = bestVal;
// Recurse on left and right
compute(k, L, mid-1, optL, bestPos);
compute(k, mid+1, R, bestPos, optR);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> K;
a.resize(n+1);
for (int i = 1; i <= n; i++) cin >> a[i];
buildSparse();
dp_prev.assign(n+1, INF);
dp_cur.assign(n+1, INF);
dp_prev[0] = 0;
// base k=1: prefix max
for (int i = 1; i <= n; i++) dp_prev[i] = max(dp_prev[i-1], a[i]);
// DP for k=2..K using divide-and-conquer optimization
for (int k = 2; k <= K; k++) {
compute(k, k, n, 0, n-1);
dp_prev = dp_cur;
}
cout << dp_prev[n] << '\n';
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |