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] \neq 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)$ 。

Codechef WEASELSC的更多相关文章

  1. Codechef SEPT17

    Codechef SEPT17 比赛链接:https://www.codechef.com/SEPT17 CHEFSUM code给定数组 a[1..n] ,求最小的下标 i ,使得 prefixsu ...

  2. 【BZOJ-3514】Codechef MARCH14 GERALD07加强版 LinkCutTree + 主席树

    3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1288  Solved: 490 ...

  3. 【BZOJ4260】 Codechef REBXOR 可持久化Trie

    看到异或就去想前缀和(⊙o⊙) 这个就是正反做一遍最大异或和更新答案 最大异或就是很经典的可持久化Trie,从高到低贪心 WA: val&(1<<(base-1))得到的并不直接是 ...

  4. codechef 两题

    前面做了这场比赛,感觉题目不错,放上来. A题目:对于数组A[],求A[U]&A[V]的最大值,因为数据弱,很多人直接排序再俩俩比较就过了. 其实这道题类似百度之星资格赛第三题XOR SUM, ...

  5. codechef January Challenge 2014 Sereja and Graph

    题目链接:http://www.codechef.com/JAN14/problems/SEAGRP [题意] 给n个点,m条边的无向图,判断是否有一种删边方案使得每个点的度恰好为1. [分析] 从结 ...

  6. BZOJ3509: [CodeChef] COUNTARI

    3509: [CodeChef] COUNTARI Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 85[Submit][St ...

  7. CodeChef CBAL

    题面: https://www.codechef.com/problems/CBAL 题解: 可以发现,我们关心的仅仅是每个字符出现次数的奇偶性,而且字符集大小仅有 26, 所以我们状态压缩,记 a[ ...

  8. CodeChef FNCS

    题面:https://www.codechef.com/problems/FNCS 题解: 我们考虑对 n 个函数进行分块,设块的大小为S. 每个块内我们维护当前其所有函数值的和,以及数组中每个元素对 ...

  9. codechef Prime Distance On Tree(树分治+FFT)

    题目链接:http://www.codechef.com/problems/PRIMEDST/ 题意:给出一棵树,边长度都是1.每次任意取出两个点(u,v),他们之间的长度为素数的概率为多大? 树分治 ...

随机推荐

  1. 【swagger】1.swagger提供开发者文档--简单集成到spring boot中【spring mvc】【spring boot】

    swagger提供开发者文档 ======================================================== 作用:想使用swagger的同学,一定是想用它来做前后台 ...

  2. AAuto如何发布EXE文件

    1 如下图所示,谷歌翻译是AAuto提供的源码,我们现在把它做成软件.点击编译,注意看底部状态栏提示,编译之后的谷歌翻译还是aau格式的,双击可以直接运行.但是体积变大了,而且已经是二进制文件,无法再 ...

  3. SolidEdge如何修改线型和线宽

    选中一条直线,然后点击如下所示两个按钮,可以分别修改线型和线宽.    

  4. 二叉查找树python实现

    1. 二叉查找树的定义: 左子树不为空的时候.左子树的结点值小于根节点,右子树不为空时,右子树的结点值大于根节点.左右子树分别为二叉查找树 2. 二叉查找树的最左边的结点即为最小值,要查找最小值.仅仅 ...

  5. LZMA C# SDK 结合 UPK 打包压缩 多目录 Unity3d实例

    上篇  LZMA C# SDK 子线程压缩与解压缩 Unity3d实例  讲了怎样使用 LZMA C# SDK 来对文件进行压缩与解压,当中提到 对于多目录能够先打包成 UPK 然后再 LZMA 压缩 ...

  6. 李洪强iOS开发之-实现点击单行View显示和隐藏Cell

    李洪强iOS开发之-实现点击单行View显示和隐藏Cell 实现的效果:  .... ....

  7. python调用nmap进行扫描

    #coding=utf-8 import nmap import optparse import threading import sys import re ''' 需安装python_nmap包, ...

  8. 第8章4节《MonkeyRunner源代码剖析》MonkeyRunner启动执行过程-启动AndroidDebugBridge

    上一节我们看到在启动AndroidDebugBridge的过程中会调用其start方法,而该方法会做2个基本的事情: 715行startAdb:开启AndroidDebugBridge 722-723 ...

  9. HDU 6061 RXD and functions NTT

    RXD and functions Problem Description RXD has a polynomial function f(x), f(x)=∑ni=0cixiRXD has a tr ...

  10. babel的安装和使用方法

    要使用Babel, 我们需要nodeJS的环境和npm, 主要安装了nodeJS, npm就默认安装了 , 现在安装nodeJS很简单了, 直接下载安装就好了: 安装es-checker 在使用Bab ...