bzoj 1010 斜率优化DP

 

我的第二道斜率DP。

 

收获:

  1、假设两个位置:p<q<i,然后让某一位置优,看其满足什么性质,所谓斜率优化就是满足:

    (g[q]-g[p])/(f[q]-f[p])  op h[i]

    要化简成这样,必须满足f函数关于位置单调,否则op(<或>)的方向就会因为f的大小关系而变化,就没有凸的性质了。

  2、斜率优化很难调试,所以当发现暴力DP和同样的方程被斜率优化了一下的答案不同时,不要去调试,直接去检查上面的各个函数是否写错或抄到代码中抄错了,

    或者重推一遍。(注意决策点是否可能会重合)

 

 1 /**************************************************************
 2     Problem: 1010
 3     User: idy002
 4     Language: C++
 5     Result: Accepted
 6     Time:116 ms
 7     Memory:3148 kb
 8 ****************************************************************/
 9  
10 #include <cstdio>
11 #define ln(A,B) ((B)-(A))
12 #define maxn 50010
13  
14 typedef long long lng;
15  
16 struct Vector {
17     lng x, y;
18     int id;
19     Vector(){}
20     Vector( lng x, lng y, int id ) : x(x), y(y), id(id) {}
21     Vector operator-( const Vector & b ) const {
22         return Vector( x-b.x, y-b.y, -1 );
23     }
24     lng operator&( const Vector & b ) const {
25         return x*b.y-y*b.x;
26     }
27 };
28 typedef Vector Point;
29  
30 int n, L;
31 int cost[maxn];
32 lng g[maxn], sum[maxn];
33 lng dp[maxn];
34 int beg, end;
35 Point qu[maxn];
36  
37 inline lng sqr( lng a ) {
38     return a*a;
39 }
40 int main() {
41     scanf( "%d%d", &n, &L );
42     sum[0] = 0;
43     for( int i=1; i<=n; i++ ) {
44         scanf( "%d", cost+i );
45         sum[i] = sum[i-1]+cost[i];
46         g[i] = sum[i]+i;
47     }
48     dp[0] = 0;
49     qu[beg=end=0] = Point( 0, 0, 0 );
50     for( int i=1; i<=n; i++ ) {
51         while( beg<end && (qu[beg+1].y-qu[beg].y)<=(qu[beg+1].x-qu[beg].x)*2*g[i] )
52             beg++;
53         int j = qu[beg].id;
54  
55         dp[i] = dp[j]+sqr(sum[i]-sum[j]-L+i-j-1);
56         Point npt = Point( g[i], dp[i]+g[i]*g[i]+2*g[i]*(L+1), i );
57         while( beg<end && (ln(qu[end-1],qu[end])&ln(qu[end-1],npt))<=0 ) 
58             end--;
59         qu[++end] = npt;
60  
61     }
62     printf( "%lld\n", dp[n] );
63 }
View Code

 

posted @ 2015-02-18 19:52  idy002  阅读(202)  评论(0编辑  收藏  举报