传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1911
【题解】
权当复习斜率优化了。
再过一遍基本式子。
本题dp方程为f[i] = max{f[j] + a(s[i]-s[j])^2 + b(s[i]-s[j]) + c}
1. 假设j<k,j没有k优
那么f[j]+a(s[i]-s[j])^2 + b(s[i]-s[j]) + c <= f[k] + a(s[i]-s[k])^2 + b(s[i]-s[k]) + c ……①
若现在到了i+1,即证下式是否成立
f[j]+a(s[i+1]-s[j])^2 + b(s[i+1]-s[j]) + c <= f[k] + a(s[i+1]-s[k])^2 + b(s[i+1]-s[k]) + c
将①代入,即证:
2ax[i+1](s[i]-s[j])+bx[i+1] <= 2ax[i+1](s[i]-s[k])+bx[i+1]
即证a(s[i]-s[j])<=a(s[i]-s[k]),由于a是负数,即证s[k]>=s[j],显然成立。
故有决策单调性
2. 推斜率式
根据①得到:
((f[j]+as[j]^2-bs[j])-(f[k]+as[k]^2-bs[k]))/(2a(s[j]-s[k])) <= s[i]
那么s[i]单调递增,相当于维护一个下凸壳。
那么直接维护就行了
尽量把左右都化成正的好搞啊
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# include <stdio.h> # include <string.h> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 1e6 + 10; const int mod = 1e9+7; # define RG register # define ST static int n, A, B, C, a[M]; int q[M], head, tail; ll f[M], s[M]; inline ld slop(int j, int k) { return (ld)((s[j]*s[j]*A-s[j]*B+f[j])-(s[k]*s[k]*A-s[k]*B+f[k]))/(ld)((s[j]-s[k])*2*A); } int main() { scanf("%d%d%d%d", &n, &A, &B, &C); for (int i=1; i<=n; ++i) { scanf("%d", a+i); s[i] = s[i-1] + a[i]; } head = 1, tail = 1; q[tail] = 0; for (int i=1; i<=n; ++i) { while(head < tail && slop(q[head], q[head+1]) <= (ld)s[i]) ++head; int t = q[head]; f[i] = f[t] + (s[i]-s[t])*(s[i]-s[t])*A + (s[i]-s[t])*B + C; while(head < tail && slop(q[tail-1], q[tail]) > slop(q[tail], i)) --tail; q[++tail] = i; } printf("%lld ", f[n]); return 0; }