题意:
大概题意就是要输出N个数字,分成连续的多段,每一段它的费用是:这串数字和的平方加上一个常数M。
题解:
状态方成 dp[i] = dp[j] + M + (sum[i]-sum[j-1])^2
#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<map>
using namespace std;
typedef __int64 lld;
#define oo 0x3f3f3f3f
#define maxn 500010
int dp[maxn];
int q[maxn];
int sum[maxn];
int M;
int TY(int i,int j)
{
return (dp[i]+sum[i]*sum[i])-(dp[j]+sum[j]*sum[j]);
}
int TX(int i,int j)
{
return 2*(sum[i]-sum[j]);
}
int GetDp(int i,int j)
{
return dp[j]+(sum[i]-sum[j])*(sum[i]-sum[j])+M;
}
int main()
{
int n,a;
while(scanf("%d %d",&n,&M)!=EOF)
{
sum[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
sum[i]=sum[i-1]+a;
}
dp[0]=0;
int Front=0,Rear=0;
q[Rear++]=0;
for(int i=1;i<=n;i++)
{
while(Front+1<Rear&&TY(q[Front+1],q[Front])<=sum[i]*TX(q[Front+1],q[Front]))
Front++;
dp[i]=GetDp(i,q[Front]);
while(Front+1<Rear&&TY(i,q[Rear-1])*TX(q[Rear-1],q[Rear-2])<=TY(q[Rear-1],q[Rear-2])*TX(i,q[Rear-1]))
Rear--;
q[Rear++]=i;
}
printf("%d\n",dp[n]);
}
return 0;
}