Print Article [HDU 3507] 斜率优化DP模板
http://acm.hdu.edu.cn/showproblem.php?pid=3507
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
const int MM = 555555; #define debug puts("wrong") #define mod 100000000 typedef __int64 int64; int N,M; int val[MM],sum[MM], dp[MM]; int head,tail,sq[MM]; /***************\ 斜率优化DP dp[i]=min(dp[j]+sqr(sum[i]-sum[j])+M | 1<=j<i) 对于队尾a b ,c插入 g[c,b]<=g[b,a] 则b对于最有策略没用 对于队首 b a,如有g[a,b]<=sum[i] 则a优于b,把b排除出队列 一开始压入0号构造的节点,防止边界条件,dp[N]为结果 对于斜率优化g[j,k]=(yj-yk)/(xj-xk)<const,则j优于k \***************/ void get_data() { int i,j,k; sum[0]=0; for(i=1;i<=N;i++) { scanf("%d",&val[i]); sum[i]=sum[i-1]+val[i]; } } int sqr(int x) {return x*x;} int cal(int x,int y) { //x>y return (dp[x]+sqr(sum[x]))-(dp[y]+sqr(sum[y])); } bool ok(int b,int a,int c) { //a>b int tmp=cal(a,b); int tt=(sum[a]-sum[b])<<1; return tmp<=(sum[c]*tt); } bool ok1(int a,int b,int c) { //c>b>a int t1,t2; t1=cal(b,a)*((sum[c]-sum[b])<<1); t2=cal(c,b)*((sum[b]-sum[a])<<1); return t2<=t1; } void solve() { int i,j,k,tt; head=tail=dp[0]=0; sq[tail++]=0; for(i=1;i<=N;i++) { while(head+1<tail && ok(sq[head],sq[head+1],i)) head++; tt=sq[head]; dp[i]=dp[tt]+sqr(sum[i]-sum[tt])+M; while(head+1<tail && ok1(sq[tail-2],sq[tail-1],i)) tail--; sq[tail++]=i; } printf("%d\n",dp[N]); } int main() { while(scanf("%d%d",&N,&M)!=EOF) get_data(),solve(); return 0; }