#include <algorithm>
#include <cassert>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
#define pb push_back
#define fst first
#define snd second
#define sz(a) int((a).size())
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vll;
const int INF = 1000 * 1000 * 1000;
const ll LLINF = 1ll << 53;
template<class T> void relaxmax(T& r, T v) { r = max(r, v); }
template<class T> void relaxmin(T& r, T v) { r = min(r, v); }
vector<int> solve_slow(int n, int k, const vector<int>& A) {
vector<int> dp(n, INF);
// A, n, k, - defined
// dp - all initialized to INF
dp[0] = A[0];
for (auto i = 1; i < n; i++) {
auto max = -INF;
for (auto j = i; j >= 0 && j >= i-k+1; j--) {
if (A[j] > max)
max = A[j];
auto sum = max + (j > 0 ? dp[j-1] : 0);
if (sum < dp[i])
dp[i] = sum;
}
}
// answer: dp[n-1]
return dp;
}
vector<int> solve_fast(int n, int k, const vector<int>& A) {
vector<int> dp(n + 1);
vector<int> C(n + 1, -INF);
vector<int> q(n + 1);
vector<int> ne(n + 1, -INF);
int qback = 0, qfront = 0;
auto cmp = [&](const int& x, const int& y) {
int vx = dp[x] + C[x], vy = dp[y] + C[y];
return vx != vy ? vx < vy : x < y;
};
set<int, decltype(cmp)> s(cmp);
dp[0] = 0;
s.insert(0);
q[qfront++] = 0;
for (int i = 1; i <= n; ++i) {
C[i] = A[i - 1];
auto it_last = lower_bound(q.begin() + qback, q.begin() + qfront, i, [=](const int& x, const int& y) {
return C[x] > C[y];
});
for (auto it = it_last; it != q.begin() + qfront; ++it) {
s.erase(*it);
C[*it] = A[i - 1];
ne[*it] = i;
if (it == it_last) s.insert(*it);
}
dp[i] = dp[*s.begin()] + C[*s.begin()];
while (qback < qfront && dp[q[qfront]] >= dp[i]) {
s.erase(q[qfront]);
qfront--;
}
q[qfront++] = i;
C[i] = -INF;
s.insert(i);
if (q[qback] == i - k) {
s.erase(i - k);
if (qback + 1 != qfront && ne[q[qback]] > q[qback + 1]) {
s.erase(q[qback + 1]);
relaxmax(C[q[qback + 1]], C[i - k]);
s.insert(q[qback + 1]);
}
qback++;
}
}
return vector<int>(dp.begin() + 1, dp.end());
}
int main() {
srand(time(NULL));
for (int t = 0; t < 100; ++t) {
int n = rand() % 1000 + 1;
int k = rand() % n + 1;
vector<int> A(n);
for (int i = 0; i < n; ++i) {
A[i] = rand() % 10000;
}
vector<int> v1 = solve_slow(n, k, A);
vector<int> v2 = solve_fast(n, k, A);
for (int i = 0; i < n; ++i)
if (v1[i] != v2[i]) {
puts("INPUT");
printf("%d %d\n", n, k);
for (int i = 0; i < n; ++i)
printf("%d ", A[i]);
puts("");
puts("OUTPUT");
for (int i = 0; i < n; ++i) printf("%d ", v1[i]);
puts("");
for (int i = 0; i < n; ++i) printf("%d ", v2[i]);
puts("");
puts("error");
return 0;
}
}
puts("good");
return 0;
}
I2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPGNhc3NlcnQ+CiNpbmNsdWRlIDxjbGltaXRzPgojaW5jbHVkZSA8Y3N0ZGlvPgojaW5jbHVkZSA8Y3N0ZGxpYj4KI2luY2x1ZGUgPGNzdHJpbmc+CiNpbmNsdWRlIDxtYXA+CiNpbmNsdWRlIDxxdWV1ZT4KI2luY2x1ZGUgPHNldD4KI2luY2x1ZGUgPHZlY3Rvcj4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKI2RlZmluZSBwYiBwdXNoX2JhY2sKI2RlZmluZSBmc3QgZmlyc3QKI2RlZmluZSBzbmQgc2Vjb25kCiNkZWZpbmUgc3ooYSkgaW50KChhKS5zaXplKCkpCnR5cGVkZWYgbG9uZyBsb25nIGxsOwp0eXBlZGVmIHBhaXI8aW50LCBpbnQ+IHBpaTsKdHlwZWRlZiBwYWlyPGxsLCBsbD4gcGxsOwp0eXBlZGVmIHZlY3RvcjxpbnQ+IHZpOwp0eXBlZGVmIHZlY3RvcjxsbD4gdmxsOwpjb25zdCBpbnQgSU5GID0gMTAwMCAqIDEwMDAgKiAxMDAwOwpjb25zdCBsbCBMTElORiA9IDFsbCA8PCA1MzsKdGVtcGxhdGU8Y2xhc3MgVD4gdm9pZCByZWxheG1heChUJiByLCBUIHYpIHsgciA9IG1heChyLCB2KTsgfQp0ZW1wbGF0ZTxjbGFzcyBUPiB2b2lkIHJlbGF4bWluKFQmIHIsIFQgdikgeyByID0gbWluKHIsIHYpOyB9Cgp2ZWN0b3I8aW50PiBzb2x2ZV9zbG93KGludCBuLCBpbnQgaywgY29uc3QgdmVjdG9yPGludD4mIEEpIHsKCXZlY3RvcjxpbnQ+IGRwKG4sIElORik7CgkvLyBBLCBuLCBrLCAtIGRlZmluZWQKCS8vIGRwIC0gYWxsIGluaXRpYWxpemVkIHRvIElORgoJZHBbMF0gPSBBWzBdOwoJZm9yIChhdXRvIGkgPSAxOyBpIDwgbjsgaSsrKSB7CgkJYXV0byBtYXggPSAtSU5GOwoJCWZvciAoYXV0byBqID0gaTsgaiA+PSAwICYmIGogPj0gaS1rKzE7IGotLSkgewoJCQlpZiAoQVtqXSA+IG1heCkKCQkJCW1heCA9IEFbal07CgkJCWF1dG8gc3VtID0gbWF4ICsgKGogPiAwID8gZHBbai0xXSA6IDApOwoJCQlpZiAoc3VtIDwgZHBbaV0pCgkJCQlkcFtpXSA9IHN1bTsKCQl9Cgl9CgkvLyBhbnN3ZXI6IGRwW24tMV0KCXJldHVybiBkcDsKfQoKdmVjdG9yPGludD4gc29sdmVfZmFzdChpbnQgbiwgaW50IGssIGNvbnN0IHZlY3RvcjxpbnQ+JiBBKSB7Cgl2ZWN0b3I8aW50PiBkcChuICsgMSk7Cgl2ZWN0b3I8aW50PiBDKG4gKyAxLCAtSU5GKTsKCXZlY3RvcjxpbnQ+IHEobiArIDEpOwoJdmVjdG9yPGludD4gbmUobiArIDEsIC1JTkYpOwoJaW50IHFiYWNrID0gMCwgcWZyb250ID0gMDsKCWF1dG8gY21wID0gWyZdKGNvbnN0IGludCYgeCwgY29uc3QgaW50JiB5KSB7CgkJaW50IHZ4ID0gZHBbeF0gKyBDW3hdLCB2eSA9IGRwW3ldICsgQ1t5XTsKCQlyZXR1cm4gdnggIT0gdnkgPyB2eCA8IHZ5IDogeCA8IHk7Cgl9OwoJc2V0PGludCwgZGVjbHR5cGUoY21wKT4gcyhjbXApOwoKCWRwWzBdID0gMDsKCXMuaW5zZXJ0KDApOwoJcVtxZnJvbnQrK10gPSAwOwoKCWZvciAoaW50IGkgPSAxOyBpIDw9IG47ICsraSkgewoJCUNbaV0gPSBBW2kgLSAxXTsKCQlhdXRvIGl0X2xhc3QgPSBsb3dlcl9ib3VuZChxLmJlZ2luKCkgKyBxYmFjaywgcS5iZWdpbigpICsgcWZyb250LCBpLCBbPV0oY29uc3QgaW50JiB4LCBjb25zdCBpbnQmIHkpIHsKCQkJcmV0dXJuIENbeF0gPiBDW3ldOwoJCX0pOwoKCQlmb3IgKGF1dG8gaXQgPSBpdF9sYXN0OyBpdCAhPSBxLmJlZ2luKCkgKyBxZnJvbnQ7ICsraXQpIHsKCQkJcy5lcmFzZSgqaXQpOwoJCQlDWyppdF0gPSBBW2kgLSAxXTsKCQkJbmVbKml0XSA9IGk7CgkJCWlmIChpdCA9PSBpdF9sYXN0KSBzLmluc2VydCgqaXQpOwoJCX0KCgkJZHBbaV0gPSBkcFsqcy5iZWdpbigpXSArIENbKnMuYmVnaW4oKV07CgoJCXdoaWxlIChxYmFjayA8IHFmcm9udCAmJiBkcFtxW3Fmcm9udF1dID49IGRwW2ldKSB7CgkJCXMuZXJhc2UocVtxZnJvbnRdKTsKCQkJcWZyb250LS07CgkJfQoKCQlxW3Fmcm9udCsrXSA9IGk7CgkJQ1tpXSA9IC1JTkY7CgkJcy5pbnNlcnQoaSk7CgkJCgkJaWYgKHFbcWJhY2tdID09IGkgLSBrKSB7CgkJCXMuZXJhc2UoaSAtIGspOwoKCQkJaWYgKHFiYWNrICsgMSAhPSBxZnJvbnQgJiYgbmVbcVtxYmFja11dID4gcVtxYmFjayArIDFdKSB7CgkJCQlzLmVyYXNlKHFbcWJhY2sgKyAxXSk7CgkJCQlyZWxheG1heChDW3FbcWJhY2sgKyAxXV0sIENbaSAtIGtdKTsKCQkJCXMuaW5zZXJ0KHFbcWJhY2sgKyAxXSk7CgkJCX0KCgkJCXFiYWNrKys7CgkJfQoJfQoKCXJldHVybiB2ZWN0b3I8aW50PihkcC5iZWdpbigpICsgMSwgZHAuZW5kKCkpOwp9CgppbnQgbWFpbigpIHsKCXNyYW5kKHRpbWUoTlVMTCkpOwoJZm9yIChpbnQgdCA9IDA7IHQgPCAxMDA7ICsrdCkgewoJCWludCBuID0gcmFuZCgpICUgMTAwMCArIDE7CgkJaW50IGsgPSByYW5kKCkgJSBuICsgMTsKCQl2ZWN0b3I8aW50PiBBKG4pOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgbjsgKytpKSB7CgkJCUFbaV0gPSByYW5kKCkgJSAxMDAwMDsKCQl9CQkJCgkJdmVjdG9yPGludD4gdjEgPSBzb2x2ZV9zbG93KG4sIGssIEEpOwoJCXZlY3RvcjxpbnQ+IHYyID0gc29sdmVfZmFzdChuLCBrLCBBKTsKCQlmb3IgKGludCBpID0gMDsgaSA8IG47ICsraSkKCQkJaWYgKHYxW2ldICE9IHYyW2ldKSB7CgkJCQlwdXRzKCJJTlBVVCIpOwoJCQkJcHJpbnRmKCIlZCAlZFxuIiwgbiwgayk7CgkJCQlmb3IgKGludCBpID0gMDsgaSA8IG47ICsraSkKCQkJCQlwcmludGYoIiVkICIsIEFbaV0pOwoJCQkJcHV0cygiIik7CgkJCQlwdXRzKCJPVVRQVVQiKTsKCQkJCWZvciAoaW50IGkgPSAwOyBpIDwgbjsgKytpKSBwcmludGYoIiVkICIsIHYxW2ldKTsKCQkJCXB1dHMoIiIpOwoJCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBuOyArK2kpIHByaW50ZigiJWQgIiwgdjJbaV0pOwoJCQkJcHV0cygiIik7CgkJCQlwdXRzKCJlcnJvciIpOwoJCQkJcmV0dXJuIDA7CgkJCX0KCX0KCXB1dHMoImdvb2QiKTsKCXJldHVybiAwOwp9Cg==