• Cut the Sequence


    题目link:http://poj.org/problem?id=3017

    Part1:

    首先拿到这道题,先得出普通的 dp。

    设 f_i 表示将前 i 个数按最优方案分为几个合法的区间的最大值之和。

    那么容易得出 dp 方程:

    f_i = min{ f_j + Max(j + 1, i) } (0 ≤ j ≤ i - 1 && Sum(j + 1, i) ≤ m);

    其中 Max(x, y) 表示 max{ a_i } (x ≤ i ≤ y),Sum(x, y) 表示 Σ a_i (x ≤ i ≤ y)。

    Part2:

    这时容易发现这个题很难直接用单调队列进行优化,那么考虑通过决策单调性来考虑这个问题。

    那么就来考虑用哪个 j 来转移最优。

    但是显然这个并不是太好考虑,那先来考虑用 j 来转移比用 j - 1 来转移更优的条件是什么。

    容易得出只有两种情况:

    Sum(j, i) > m && Sum(j + 1, i) ≤ m;

    f_j + Max(j + 1, i) < f_{j - 1} + Max(j, i);

    那么满足这两种情况之一就变成了 j 是最优转移的必要条件。

    但是好像这个题不能像普通的单调队列优化 dp 的题一样来找到队首这样一个唯一的最优解,那么现在只能去考虑一下找到一些 j,使得最优的转移包含在这些 j 里面就行了(dp 虽然需要不漏,但是不需要不重)。

    那么现在就考虑如何去找到上面的两种情况的 j 并依次进行转移就行了。

    Part2.1:

    这里第一种情况比较容易考虑。

    容易得到对于每一个 i 来说,这样的 j 只可能会存在一个(因为它是一个分界点)。

    然后就可以二分去找这样的 j,具体实现可以使用 STL 中的 lower_bound 函数(找到第一个大于或等于 Sum(1, i) - m 的 Sum(1, j),j 就是答案)。

    Part2.2:

    这里可能会较为困难一些,那么先看一看 f_j 和 f_{j - 1} 的关系。

    它们的关系其实是 f_j ≥ f_{j - 1},这里给出证明:

    考虑使用前 j 个数的最优分区间方案的分界点去分前 j 个数,这里容易证明这样是一个分前 j - 1 个数的合法的方案,但不一定是最优的方案,并且也容易证明这样分的所有区间最大值之和是小于或等于前 j 个数的最优方案的所有区间最大值之和的(因为只会有最后一个区间的数比前 j 个数的方案的最后一个区间的数少一个,但是最后一个区间的最大值不可能比前 j 个数的大)。所以既然如这般如此,仅仅是一个合法的方案就比前 j 个数的最优方案要好(或相等),那 f_j 一定大于或等于 f_{j - 1},证毕。

    既然 f_j ≥ f_{j - 1},还想要 f_j + Max(j + 1, i) < f_{j - 1} + Max(j, i),那么必须就得 Max(j + 1, i) < Max(j, i),化简一下就是 a_j = Max(i, j)。

    那么现在就是考虑把上面这个化简过的式子里的 j 给都找到并进行转移了,于是考虑接着进行转化

  • 相关阅读:
    c++ stringstream
    c语言中字符串数组初始化的一点总结&& c++访问控制的三种方式
    Leetcode 2. Add Two Numbers(medium)
    面试题---反转一个字符串
    编程题---在数组中取一个位置,让这个位置之前的数的和与之后的和的差绝对值最小
    美团面试准备
    Leetcode 101. Symmetric Tree(easy)
    Leetcode 665. Non-decreasing Array(Easy)
    617. Merge Two Binary Trees(Easy)
    423. Reconstruct Original Digits from English(Medium)
  • 原文地址:https://www.cnblogs.com/qqq1112/p/15159452.html
Copyright © 2020-2023  润新知