斜率dp简单题
#include <STDIO.H>
#include <STRING.H>
/*
dp[i] = min( dp[j] + M + (...)^2 )
*/
const int MAXN = 500005;
int n, m;
int da[MAXN], sum[MAXN], dp[MAXN];
int q[MAXN], head, tail;
int getDP(int i, int j)
{
return dp[j] + m + (sum[i]-sum[j])*(sum[i]-sum[j]);
}
int getUP(int k, int j)
{
return dp[j]-dp[k] + sum[j]*sum[j] - sum[k]*sum[k];
}
int getDOWN(int k, int j)
{
return 2*(sum[j]-sum[k]);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
while (scanf("%d%d", &n, &m) == 2)
{
int i;
for (i = 1; i<= n; i++)
scanf("%d", &da[i]);
for (i = 1; i<= n; ++i)
sum[i] = sum[i-1]+da[i];
head = tail = 0;
q[tail++] = 0;
for (i = 1; i<= n; i++)
{
while (tail-head>1 && getUP(q[head],q[head+1])<=sum[i]*getDOWN(q[head],q[head+1]))
head++;
dp[i] = getDP(i, q[head]);
while (tail-head>1 && getUP(q[tail-2],q[tail-1])*getDOWN(q[tail-1],i)
>=getUP(q[tail-1],i)*getDOWN(q[tail-2],q[tail-1]))
tail--;
q[tail++] = i;
}
printf("%d\n", dp[n]);
}
return 0;
}