【BZOJ3156】防御准备 斜率优化DP

  裸题,注意:基本的判断(求Min还是Max),因为是顺着做的,且最后一个a[i]一定要取到,所以是f[n]。

  DP:f[i]=min(f[j]+(i-j-1)*(i-j)/2+a[i])

  依旧设x>y且f[x]优于f[y](原来是通用方法。。。)

  2*(f[x]-f[y]) +x^2+x-y^2-y=2*i*(x-y) ok了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #define N 1000000+100
 4 #define ll long long 
 5 using namespace std;
 6 ll f[N];
 7 int a[N],q[N];
 8 int n,i,l,r;
 9 inline int read()
10 {
11     int ans=0,f=1;
12     char c;
13     while (!isdigit(c=getchar())) if (c=='-') f=-1;
14     ans=c-'0';
15     while (isdigit(c=getchar())) ans=ans*10+c-'0';
16     return ans*f;
17 }
18 inline ll Pow(ll x) {return x*x;}
19 inline double Get(int x,int y) {return (double)(2*(f[x]-f[y])+Pow(x)-Pow(y)+x-y)/(double)(x-y);}
20 int main()
21 {
22     n=read();
23     for (int i=1;i<=n;i++) a[i]=read();
24     for (int i=1;i<=n;i++)
25     {
26         while (l<r && Get(q[l+1],q[l])<2*i) l++;
27         f[i]=f[q[l]]+(i-q[l]-1)*(i-q[l])/2+a[i];
28         while (l<r && Get(i,q[r])<Get(q[r],q[r-1])) r--;
29         q[++r]=i;
30     }
31     printf("%lld",f[n]);
32     return 0;
33 }
View Code

Description

 

Input

第一行为一个整数N表示战线的总长度。

第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai。

 

Output

共一个整数,表示最小的战线花费值。

 

Sample Input



10
2 3 1 5 4 5 6 3 1 2

Sample Output


18

HINT

 



1<=N<=10^6,1<=Ai<=10^9

 

Source

posted @ 2016-04-23 19:56  DMoon  阅读(489)  评论(0编辑  收藏  举报