bzoj 2011

 

决策单调性,对于一个1D/1D(状态是一维,转移也是一维)的DP,如果DP的决策具有单调性,那么就可以做到O(nlogn)的复杂度完成DP。

感谢《1D/1D  动态规划优化初步》的作者。

 

 1 /**************************************************************
 2     Problem: 2216
 3     User: idy002
 4     Language: C++
 5     Result: Accepted
 6     Time:4916 ms
 7     Memory:14476 kb
 8 ****************************************************************/
 9  
10 #include <cstdio>
11 #include <algorithm>
12 #include <cmath>
13 #define N 500010
14 using namespace std;
15  
16 struct Trid {
17     int p, l, r;
18     Trid(){}
19     Trid( int p, int l, int r ):p(p),l(l),r(r){}
20 };
21  
22 int n;
23 int aa[N];
24 int f[N], g[N], h[N];
25 Trid stk[N]; int top;
26  
27 double calc( int j, int i ) {
28     return aa[j]-aa[i]+sqrt(abs(i-j));
29 }
30 void dodp( int dp[N] ) {
31     stk[top=1] = Trid(1,1,n);
32     for( int i=2; i<n; i++ ) {
33         if( calc(stk[top].p,n)>calc(i,n) ) continue;
34          
35         while( stk[top].l>=i && 
36                 calc(stk[top].p,stk[top].l)<calc(i,stk[top].l) )
37             top--;
38         if( stk[top].r==i-1 ) {
39             stk[++top] = Trid( i, i, n );
40         } else {
41             int lf = max( stk[top].l+1, i );
42             int rg = min( stk[top].r+1, n );
43             int p = stk[top].p;
44             while( lf<rg ) {
45                 int mid=(lf+rg)>>1;
46                 if( calc(p,mid) > calc(i,mid) ) lf=mid+1;
47                 else rg=mid;
48             }
49             stk[top].r = lf-1;
50             stk[++top] = Trid( i, lf, n );
51         }
52     }
53     for( int i=1; i<=top; i++ ) 
54         for( int j=stk[i].l; j<=stk[i].r; j++ )
55             dp[j] = stk[i].p;
56 }
57 int main() {
58     scanf( "%d", &n );
59     for( int i=1; i<=n; i++ )
60         scanf( "%d", aa+i );
61     dodp(f);
62     reverse( aa+1, aa+1+n );
63     dodp(g);
64     reverse( aa+1, aa+1+n );
65  
66     for( int i=1; i<=n; i++ ) 
67         g[i] = n+1-g[i];
68     reverse( g+1, g+1+n );
69  
70     for( int i=1; i<=n; i++ )
71         if( calc(f[i],i)>calc(g[i],i) ) h[i]=f[i];
72         else h[i]=g[i];
73     for( int i=1; i<=n; i++ )
74         printf( "%lld\n", (long long)ceil(calc(h[i],i)) );
75 }
View Code

 

posted @ 2015-04-08 16:38  idy002  阅读(191)  评论(0编辑  收藏  举报