干草堆

先倒序处理(为什么下文会说),然后就变成了划分尽量多的段,使得每段的和单调不减

很容易设置出一个状态\(f[i][j]\)表示前\(i\)堆草,最后一段是\([j,i]\)的最大高度,方程也很容易推导,但是时空复杂度显然炸掉

那么此时我们就应该思考,要么就是利用数组值来搞一些事情(一般是交换两种维度的信息,另一种是可行性转最优性,这里显然都不行),要么就是发现某些引理(一般用贪心)

我们这里就可以想,对一个前\(i\)堆草来说,假设能堆到最高高度的方案有若干种,那么我们想要哪一种呢?显然是想要最后一段最小的一种,根据决策包容性易证

于是可以设\(f[i]\)表示前\(i\)堆草能够堆到的最大高度,\(g[i]\)表示所有最大高度的方案中最后一段最小的一种方案的最后一段的长度,\(s[i]\)表示前缀和,于是就有

\[f[i]=max_{j<i,s[i]-s[j]≥g[j]}(f[j])+1 \]

这个时候我们倒序处理的原因就来了。对上面这个式子,看起来有两个条件要满足(在满足\(max(f[j])\)最大的情况下让\(j\)最大,这样可以让\(g[i]\)最小)导致需要使用数据结构优化DP,其实当\(j\)最大的时候\(f[j]\)也一定是最大的,因为\(f\)是单调不减的(我们倒序处理了,现在是让每段的和单调不减,如果\(f[i]<f[j]\)\(i>j\),那么对于\(j\)的方案,我们直接把\([j+1,i]\)这些干草全部放在\(j\)的方案的最后一段就好了,这样就有\(f[i]=f[j]\)了)

然后这个时候我们就可以用单调队列解决问题了,想一下单调队列怎么处理:此时单调队列里面存的是所有可能的决策点,但是我们没有必要建立二叉堆和单调队列的映射,因为根据上面的引理,我们只要一直弹出队首直到不满足\(s[i]-s[j]≥g[j]\),最后一个弹出的就是最佳决策

update 2024.4.14

重做这道题目,隐约记得是需要倒序处理的,所以直接就往倒序处理想了

然后想了许久,得出来了上面的DP方程,但实际上仅仅凭这些是无法说明这个方法的正确性的

因为可能对当前的\(i\),某个\(j\)满足\(s[i]-s[j]<g[j]\)但是对\(j\)来说存在另一种不是最高高度的方案,最底层却更小,然后可以把\([j+1,i]\)这些干草放在这个方案的最底端而且新的这个方案就是对于\(i\)来说的最优的方案

所以我们需要证明,对于所有最优的方案,我们找到底端最小的一种方案,那么对于其他所有的方案,底端都不会比我们找出来的这个最优方案更小

当然考试的时候可以猜这个结论,我重做的时候就是一直卡在这个结论的证明上面了

证明实际并不好证明:

设我们找出来的最优方案为\(P_1\),假设存在另一种方案\(P_2\)\(P_2\)的高度比\(P_1\)小但是最底端却比\(P_1\)小,假设\(P_2\)的高度为\(h\),我们依次从最底端往上进行比较,设第\(i\)\(P_1\)在序列(注意在证明中我们还没有倒序考虑序列,这个序列就是题目给出来的序列)中对应的一段的编号最大干草编号为\(a_i\),同理设出\(P_2\)\(b_i\)。那么\(P_1\)的分段就是\([a_1=1,a_2],[a_2+1,a_3],...\)\(P_2\)的分段就是\([b_1=1,b_2],[b_2+1,b_3],...,[b_{h-1}+1,b_h=n]\)

由题,\(a_2>b_2\)(因为\(P_2\)的底端更小,也就是这一段的和更小),\(a_h<b_h=n\),所以中间一定存在一个位置\(k\),满足\(a_{k-1}≥b_{k-1}\)\(a_k≤b_k\),我们找到最小的这样的\(k\),那么就说明\(P_1\)的第\(k\)层的干草全部都被包含在\(P_2\)的第\(k\)层的干草中,那么我们构造一个新的方案,最底层到第\(k-1\)层取\(P_2\)的分法,第\(k+1\)层到第\(H\)\(P_1\)的高度)层取\(P_1\)的分法,然后没有被取到的剩下的干草就放在第\(k\)层,不难发现这个新的方法是合法的,而且他的高度与\(P_1\)一样但是最底层却比\(P_1\)的最底层更小,与我们最开始的假设矛盾,证毕

有了这个证明,我们才可以说明我们的DP是正确的

update 2024.7.5

其实我们最开始设出\(f[i][j]\)表示前\(i\)堆草,最后一段是\([j,i]\)的最大高度发现推不走之后,也有可能使我们的方向搞错了,就像“围栏障碍训练场”这道题目一样,所以我们考虑倒序,也许可以发现上面的贪心

可以想一下数据结构如何优化:对\(f\)的快速查询就不说了,对\(g[i]\),我们有\(g[i]=s[i]-max(s[j])\),要求\(f[j]==f[i]-1\),于是我们令\(d[i]\)表示\(f\)值为\(i\)\(s\)值最大的下标,这样就可以\(O(1)\)更新了

但是这里证明\(f\)单调的思想与“裁剪序列”这道题目非常像,也可以记住

posted @ 2024-02-03 17:29  最爱丁珰  阅读(4)  评论(0编辑  收藏  举报