斜率优化dp。比较入门的斜率优化dp。从的Accept大神那学到的,讲的很好,很适合我这种菜鸟学习。。。但是那个图好像画的有点儿问题。应该是下凸的图形。只有斜率公式能够使单调才能用斜率优化。这道题accept大神讲的很明白了,同学们可以去看看。http://www.cnblogs.com/ka200812/archive/2012/08/03/2621345.html
本来想自己理解一下然后写一下,没想到写着就写的和accept的一样了。。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int N = 500500;
int sum[N], dp[N], d[N];
int n, m;
int DB(int a){return a * a;}
int getUP(int i, int j)
{
return dp[i] + DB(sum[i]) - dp[j] - DB(sum[j]);
}
int getDOWN(int i, int j)
{
return 2 * (sum[i] - sum[j]);
}
int getDP(int i, int j)
{
return dp[j] + DB(sum[i] -sum[j]) + m;
}
int main()
{
//freopen("input.txt", "r", stdin);
int l, r;
while(scanf("%d%d", &n, &m) != EOF)
{
sum[0] = 0;dp[0] = 0;
for(int i = 1; i <= n; i ++)
{
scanf("%d", &sum[i]);
sum[i] += sum[i - 1];
}
l = r = 0;
d[r ++] = 0;
for(int i = 1; i <= n; i ++)
{
while(l + 1 < r && getUP(d[l + 1], d[l]) <= getDOWN(d[l + 1], d[l]) * sum[i])
l ++;
dp[i] = getDP(i, d[l]);
while(l + 1 < r && getUP(d[r - 1], d[r - 2]) * getDOWN(i, d[r - 1]) >= getDOWN(d[r - 1], d[r - 2]) * getUP(i, d[r - 1]))
r --;
d[r ++] = i;
}
printf("%d\n", dp[n]);
}
}