bzoj1233 干草堆 - 单调队列优化dp

Posted cychester

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1233 干草堆 - 单调队列优化dp相关的知识,希望对你有一定的参考价值。

问题描述:

  若有干个干草, 分别有各自的宽度, 要求将它们按顺序摆放, 并且每层的宽度不大于 它的下面一层 ,  求最多叠几层

题解:    

    zkw神牛证明了: 底边最短, 层数最高         证明: 传送门

 

    接下来我们就可以根据这个结论进行dp。 前缀和sum, 以及 F[ i ]第 i 个数之后的干草叠起来后, 底层的最短宽度, 以及 H[ i ] 表示 第i个后的干草堆最高叠几层

    有转移方程 : F[ i ] = min( sum[ j - 1] - sum[i - 1] ) ( j > i && sum[ j - 1] - sum[ i - 1] >= f[ j ] )  由于前缀和从前往后是递增的, 所以 j 越小越好。

    又因为要满足 sum[ j - 1] - f[ j ] >= sum[ i - 1 ] , 所以 sum[ j - 1] - f[ j ] 越大越好, 可以用单调队列来使决策具有单调性, 每次取出队首就是最优决策

    

代码

  

技术分享图片
 1 #include<cstring>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define rd read()
 5 #define rep(i,a,b) for( int i = (a); i <= (b); ++i )
 6 #define per(i,a,b) for( int i = (a); i >= (b); --i )
 7 using namespace std;
 8 
 9 const int N = 1e5 + 1e4;
10 
11 int n, a[N], sum[N], f[N], h[N], q[N];
12 
13 int read() {
14     int X = 0, p = 1; char c = getchar();
15     for(; c > 9 || c < 0; c = getchar() ) if( c == - ) p = -1;
16     for(; c >= 0 && c <= 9; c = getchar() ) X = X * 10 + c - 0;
17     return X * p;
18 }
19 
20 int main()
21 {
22     n = rd;
23     rep( i, 1, n ) sum[i] = sum[i - 1] + rd;
24     int l = 1, r = 1;
25     q[r] = n + 1;
26     sum[n + 1] = sum[n];
27     per( i, n, 1 ) {
28         while( l < r && f[ q[l + 1] ] <= sum[ q[l + 1] - 1] - sum[i - 1] ) l++;
29         f[i] = sum[ q[l] - 1] - sum[i - 1];
30         h[i] = h[q[l]] + 1;
31         while( l < r && sum[q[r] - 1] - f[q[r]] <= sum[i - 1] - f[i] ) r--;
32         q[++r] = i;
33     }
34     printf("%d
",h[1]);
35 }
View Code

 

以上是关于bzoj1233 干草堆 - 单调队列优化dp的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2442&&codevs4654 单调队列优化dp

bzoj 1855 dp + 单调队列优化

bzoj1855||hdu3401股票交易——单调队列优化dp

●BZOJ 1233 [Usaco2009Open] 干草堆 tower

bzoj3831 [Poi2014]Little Bird 单调队列优化dp

bzoj1044[HAOI2008]木棍分割 单调队列优化dp