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 }