zoukankan      html  css  js  c++  java
  • Codechef WEASELSC

    WEASELSC code

    给定一个高度图 a[1..n] ,要求你减少图中一些地方的高度,使得得到的图是一个不超过 K 级的楼梯,要求楼梯的面积最大(即得到的图中所有位置的高度之和最大)。

    这题题面特别不清晰,我们现在要形式化这个问题。

    给定一个数组 a[1..n] ,要求找到一个数组 b[1..n],使得
    1. 对任意$1 le i le n$,有$0 le b[i] le a[i]$。
    2. 存在 $1 le L le R le n$,使得
    2.0. 对任意 $1 le i < L$ 或 $R < i le n$,都有$b[i] = 0$。
    2.1. 子数组 b[L..R] 是一个楼梯,并且楼梯级数不超过 K 。
    3. 最大化 $sum(b) = sum_{i=1}^n b[i]$。

    一个数组 a[1..n] 是一个楼梯,如果 a[1..n] 单调,即 a[1..n] 单调(非严格)递增 或 单调(非严格)递减。

    一个楼梯 a[1..n] 的级数为
    $$ step(a[1..n]) = sum_{i=2}^n [a[i] eq a[i-1]]. $$

    解:

    这题是贪心与动态规划结合的题目,所以在解题之前要观察题目的一些性质。

    观察0:若我们解决了单调递增楼梯的问题,则我们把整个数组 a[1..n] 翻转过来,即可解决单调递减楼梯的问题。

    因此我们只需要考虑单调递增楼梯的求解。

    观察1:若b[1..n]是满足条件并且最大化 $sum(b)$ 的数组,则存在 $1 le i le n$,使得 $b[i] = a[i]$ 且 b[i] 是最高的那一级楼梯。

    观察2:若我们选定了某个 $1 le i le n$,使得 $b[i] = a[i]$ 作为整个楼梯最高级的高度,则贪心地往两边延伸,直到碰到比 a[i] 小的位置为止。

    于是,我们可枚举最高级楼梯的高度所在的位置 i,从左右延伸得到一个高度为 a[i] 的平台,范围是 [L, R] 。
    由于当前枚举的是最高级的楼梯,因此在 R 的右边不存在任何楼梯,我们只需要考虑 L 的左边的情况。
    此时,必定有 a[L-1] < a[L] (我们额外定义 a[0] = -1 以处理边界情况)。
    于是接下来的问题就是,如何利用 1..L-1 来建造 K-1 级楼梯,并且要求楼梯最右侧位于 L-1,以及使得楼梯的高度之和最大,我们令 f[L][K] 表示这个最大值。
    对特定的 a[i],我们把上述 L, R 分别记作 L[i], R[i]。

    有动态规划方程
    $$ f[i][k] = max_{0 le j < i} { f[j][k-1] + (i-j)a[j] : a[j] < a[p], forall j < p < i }. $$
    以及边界条件 $f[0][k] = f[i][0] = 0$。

    这是一个可以斜率优化的式子,我们把式子整理一遍,可得
    $$ f[i][k] = max_{0 le j < i} { f[j][k-1]-ja[j] + ia[j] : a[j] < a[p], forall j < p < i }. $$
    若令$x[j] = a[j], y[j] = f[j][k-1]-ja[j]$,则式子更加直观
    $$ f[i][k] = max_{0 le j < i} { i x[j] + y[j] : a[j] < a[p], forall j < p < i }. $$

    我们现在考虑哪些 j 可以被纳入动态规划的候选名单中。
    我们记
    $$ S(i) = { j : 0 le j < i, a[j] < a[p], forall j < p < i }. $$

    观察3:如果L[i] = L[j],则S(i) = S(j)。

    观察4:如果$j_1, j_2 in S(i)$,则 $j_1 < j_2$ 当且仅当 $a[j_1] < a[j_2]$。

    于是,我们在依次枚举 j = 1..n 的过程中,可以用单调队列维护集合 S,而拥有相同当前集合 S = S(i) 的 i 则满足 L[i] = j。
    这时,集合 S 中用单调队列维护二维上凸壳 (x[j], y[j]) ,对于每个 i,可以利用二分法求得斜率为 i 的取最优解的二维点,并带入计算得到 f[i][k]。

    时间复杂度 $O(Kn log n)$ 。

  • 相关阅读:
    补发《超级迷宫》站立会议九
    补发《超级迷宫》站立会议八
    补发《超级迷宫》站立会议七
    补发《超级迷宫》站立会议六
    一周开发项目
    所学的内容
    开发项目和所用时间 感想
    自我介绍
    大容量数据转移操作命令——BULK INSERT(类似于BCP)
    字符编码与文件处理
  • 原文地址:https://www.cnblogs.com/TinyWong/p/7479466.html
Copyright © 2011-2022 走看看