题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3507
kuangbin大佬的博客讲的非常清楚orzhttp://www.cnblogs.com/kuangbin/archive/2012/08/26/2657650.html
#include<bits/stdc++.h> using namespace std; typedef long long ll; deque<ll> q; const int maxn=500005; int a[maxn]; ll sum[maxn]; ll dp[maxn]; bool calc(int k,int j,int i) { return dp[j]+sum[j]*sum[j]-dp[k]-sum[k]*sum[k]<=2ll*sum[i]*(sum[j]-sum[k]); } bool judge(int k,int j,int i) { return (dp[j]+sum[j]*sum[j]-dp[k]-sum[k]*sum[k])*(sum[i]-sum[j])>=(dp[i]+sum[i]*sum[i]-dp[j]-sum[j]*sum[j])*(sum[j]-sum[k]); } int main() { int n,m; while (~scanf("%d%d",&n,&m)) { while (!q.empty()) q.pop_back(); for (int i=1;i<=n;i++) scanf("%d",&a[i]); sum[0]=0; for (int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i]; dp[0]=0; q.push_back(0); for (int i=1;i<=n;i++) { while (q.size()>1) { auto it=q.begin(); int k=*it; int j=*(++it); if (calc(k,j,i)) q.pop_front(); else break; } int b=q.front(); dp[i]=dp[b]+m+(sum[i]-sum[b])*(sum[i]-sum[b]); while (q.size()>1) { auto it=q.end(); int j=*(--it); int k=*(--it); if (judge(k,j,i)) q.pop_back(); else break; } q.push_back(i); } printf("%I64d ",dp[n]); } return 0; }