説明
入力
出力
サンプル入力
4
3 1 0 2
サンプル出力
5
4
3
1
データ制約
思考
あなたが初めに悪いと一緒に重ね合わせてはいけない、鎧をオーバーレイしたい場合はまだ、再びアーマーアーマー0:00重畳なります。
したがって、我々は短いDPを設定することができ、提供F [i] [j]が位置し、無電力値に滞在する電流iを示し、合計の電流値は、J装甲消費
。1. 1-I〜損傷と集計されている最小傷害とは、明らかにFがある[I] [J] + C [i]の[P]→F [I + P] [J + P] とF [i]は[J] + [I]→F [I + +1] [J]、C
[i]は[P]私は鎧I〜I + P-1、及び損傷、明らかにC [i]と[P] =においてPの重ね合わせを表し 、C [I + 1] [P-1] + MAX([I] -p、0)は、 これ
はO(n ^ 3)を行うことができます。
ここで、この第一のDPを最適化する方法を検討し、移行が観察された発現は、各時刻Fを見出すことができるである[I] [J] Fに転送される[I + P] [J + P] への状態移行
の大きさと第2の大き差は変化せず、その後、C [IP] [P + J]> C = [I]見出すことができる性質を観察Jパケットの状態のIJによれば、
二次転写のその後の除去、に転送します同じグループのために、我々は伝達係数を見て、今のFを考える[I + D] [I ] とF [J + D] [J ]
Fの[D + z]は[Z ] の転送(I > j)が良好である、F参照[I + D] [I ] Fにシフトする[I + D] [I ] + C [I + D] [ZI]→[D + Z] F [ Z]および
F [J + D] [J ] + C [J + D] [ZJ]→F [D + Z] [z]は、 zの増加として見ることができる、C [J + D] [ ZJ ] -c [I +値d] [ZI]を徐々に、単純な用語で、低減され
ていること、比較的小さなZは、F [I + D] [I ] より好ましくから転送、大きなZのためのfで[J + D] [J ] より良いから転送され、我々はできます
スタックモノトーンを更新する、最適な決定間隔を維持するために単調スタックを維持するために、単調決定は、バイナリポイントを必要とし、したがって、複雑性はO(2 ^ N-ある
ログN-)
コード
#include <bits/stdc++.h>
#define F(i, a, b) for (int i = a; i <= b; i ++)
#define G(i, a, b) for (int i = a; i >= b; i --)
#define mem(a, b) memset(a, b, sizeof a)
#define mn(a, b) ((a) = min(a, b))
const int N = 4010;
using namespace std;
int n, TOT, sum, v, ans, G[N][N];
int a[2 * N], ct[N], C[N][N], Len[N], g[N][N], f[2 * N][N];
int main() {
freopen("griffin.in", "r", stdin);
freopen("griffin.out", "w", stdout);
scanf("%d", &n), Len[0] = 1, g[0][1] = 1e9;
F(i, 1, n) scanf("%d", &a[i]), Len[i] = 1, g[i][1] = 1e9;
F(i, 1, n) {
mem(ct, 0);
F(j, i, n)
if (a[j] + j - i <= n) ct[a[j] + j - i] ++;
C[i][0] = a[i], TOT = - ct[0], sum = 0;
F(j, 1, n) {
if (i + j - 1 <= n) TOT ++, sum += a[i + j - 1];
sum -= TOT, TOT -= ct[j], C[i][j] = sum;
}
}
mem(f, 7), f[0][0] = 0;
F(i, 0, n - 1) {
F(d, 0, 2 * n - i - 1)
mn(f[i + (d + 1)][i], f[i + d][i] + a[i + d + 1]);
if (i > 0) {
F(d, 0, n - i - 1) {
v = G[d][Len[d]];
if (f[i + d][i] >= f[v + d][v]) continue;
ans = i;
for (int l = i + 1, r = n; l <= r; ) {
int m = l + r >> 1;
if (f[i + d][i] + C[i + d + 1][m - i] < f[v + d][v] + C[v + d + 1][m - v])
ans = m, l = m + 1;
else
r = m - 1;
}
G[d][++ Len[d]] = i, g[d][Len[d]] = ans;
}
}
F(d, 0, 2 * n - i - 1) {
while (d < n && i + 1 > g[d][Len[d]]) Len[d] --;
v = d >= n ? 0 : G[d][Len[d]];
mn(f[(i + 1) + d][i + 1], f[v + d][v] + (v + d + 1 > n ? 0 : C[v + d + 1][i + 1 - v]));
}
}
F(i, 1, n) {
ans = 1e15;
F(k, n, n + n - 1)
ans = min(ans, f[k][i]);
printf("%d\n", ans);
}
}