题目大意:
分析:
设
d
p
i
dp_i
dpi表示分割了前i个,最大能得到的价值
初值:
d
p
i
=
f
(
m
i
n
i
=
1
i
a
i
)
dp_{i}=f(min_{i=1}^{i}a_i)
dpi=f(mini=1iai)
转移就是
d
p
i
=
d
p
j
+
f
(
m
i
n
i
=
j
+
1
i
a
j
)
dp_{i}=dp_{j}+f(min_{i=j+1}^{i}a_j)
dpi=dpj+f(mini=j+1iaj)
然后用单调栈维护即可
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <cstring>
#include <algorithm>
#define rep(i, st, ed) for (int i = st; i <= ed; i++)
#define rwp(i, ed, st) for (int i = ed; i >= st; i--)
#define N 200005
using namespace std;
typedef long long ll;
ll cmin[N], dp[N], a[N], h[N], A, B, C, D, minnum = a[1];
int n, cnt;
ll Calc(ll x) {
return A * x * x * x + B * x * x + C * x + D;
}
int main() {
freopen("min.in", "r", stdin);
freopen("min.out", "w", stdout);
scanf("%d %lld %lld %lld %lld", &n, &A, &B, &C, &D);
rep(i, 1, n) scanf("%lld", &a[i]);
cmin[++cnt] = a[1]; h[cnt] = 0;
rep(i, 1, n) {
dp[i] = Calc(minnum);
rep(j, 1, cnt) dp[i] = max(dp[i], h[j] + Calc(cmin[j]));
if (i == n) break;
ll hmax = dp[i];
while (cnt >= 1 && cmin[cnt] >= a[i + 1]) hmax = max(hmax, h[cnt]), cnt--;
cmin[++cnt] = a[i + 1], h[cnt] = hmax;
minnum = min(minnum, a[i + 1]);
}
printf("%lld\n", dp[n]);
return 0;
}