一、题目
二、解法
方法1 fnm dp
看数据范围,如果从 d p dp dp的角度来思考,那么设 d p [ i ] dp[i] dp[i]为 . . . . . . ...... ......(只有这种定义可行一点了)
增加高度很重要?状态定义又不能要。那么我们定义 d p [ i ] dp[i] dp[i]为 i i i作为不动建筑的最小花费(分为两种),问题是这种定义是否能转移?
d p dp dp的本质是所有可能情况的枚举,我们不妨枚举一段都升高了(显然会枚举所有情况),如何升高我们暂时还不知道,需要分析。首先 i i i和 j j j(这一段的左边那个)一定要比这一整段都高,不然都升高显然是吃力不讨好的操作(注意,这是转移条件哦)。
然后我们知道这一段中最高的建筑升高了,但如果他两边的建筑升得没有这么高,那还不如他不升高呢!所以他两边的建筑也会升高到同一高度,进而得出这一整段都会最终升高到同一高度。设这个高度是
t
t
t,转移:
d
p
[
i
]
=
d
p
[
j
]
+
∑
k
=
j
+
1
i
−
1
(
t
−
a
[
k
]
)
+
c
(
a
[
i
]
+
a
[
j
]
−
2
t
)
dp[i]=dp[j]+\sum_{k=j+1}^{i-1}(t-a[k])+c(a[i]+a[j]-2t)
dp[i]=dp[j]+k=j+1∑i−1(t−a[k])+c(a[i]+a[j]−2t)那么
t
t
t 的最优取值可以通过二次函数来确定,时间复杂度
O
(
n
2
)
O(n^2)
O(n2)
优化转移的主要方法是观察转移条件,我们可以维护一个单调栈。一个元素插入单调栈时弹出比他小的元素,这些元素是可以转移的(其他元素根据单调栈的性质是不可以转移的)。然后没弹出的那个也是可以转移的,所以有效的转移是 O ( n ) O(n) O(n)的,用单调栈可以达到这一点。
方法2 jzm yyds
这种方法的核心思想是缩小问题规模
如果缩小问题规模?对于一开始的形式,最高的建筑是肯定不会升高的,那么以他为界把原序列花费成两部分。以此类推,一直划分下去(相当于一颗笛卡尔树),看图:
左边的部分如果原来就没到 max \max max(他那一块的最高值),那么就不需要提升了(因为你传下去的时候没有提升,现在肯定不能提升了)。右边的部分如果提高到了 max \max max,那么是可以继续提高的(会缩小和高度的差距),右边提升的高度可以通过二次函数来计算(和 d p dp dp的方法一样)
什么都没有