我读过这篇社论,但它很短,声称我不明白为什么这是真的。为什么它等同于找到1*2*1*2*
的最长子序列?有人可以一步一步解释解决方案,并在每一步证明索赔的合理性吗? http://codeforces.com/contest/934/problem/C
以下是社论中的“解决方案”,但正如我所说的那样,它很短,我不明白。希望有人可以一步一步地指导我解决问题的方法,而不是像这里的解决方案那样。感谢。
从
1 ≤ ai ≤ 2
开始,它等同于找到最长的子序列1 * 2 * 1 * 2 *
。通过简单的动态编程,我们可以找到它O(n)
或O(n2)
时间。您可以在模型中看到O(n2)
解决方案 解决方案如下这里我们介绍一种O(n)方法:自从 我们可以将子序列分成4个部分(11...22...11...22...)
可以设置dp[i][j](i = 1...n, j = 0..3)
是最长的子序列a[1...i]
j
个GetPathHandler()
部分。
答案 0 :(得分:0)
我也认为引用的解释不是很清楚。这是另一种看法。
您可以折叠原始数组
1 1 2 2 2 1 1 2 2 1
加入加权数组
2 3 2 2 1
^ ^ ^ ^ ^
1 2 1 2 1
其中顶部的数字表示原始数组中重复值的连续条带的长度。
我们可以说服自己
因此,加权数组包含足够的信息来解决问题。我们想要翻转加权数组s.t.的连续切片。与某些连续单调序列相关的权重之和最大化。
具体来说,我们希望以一种连续的单调序列112
,122
,211
或221
具有最大权重的方式执行翻转。
动态编程的一种方法是创建4个辅助数组。
A[i]
:i右边任意1的最大权重。B[i]
:i左边任意1的最大重量。C[i]
:i右边任意2的最大权重。D[i]
:i左边任意2的最大权重。假设如果访问A,B,C,D
中的任何一个超出范围,则返回的值为0
。
我们初始化x = 0
并通过权重Arr = [1, 2, 1, 2, 1]
的数组W = [2, 3, 2, 2, 1]
进行一次传递。在每个索引i
,我们有2个案例:
Arr[i:i+2] == 1 2
。在这种情况下,我们设置
x = max(x, W[i] + W[i+1] + C[i+1], W[i] + W[i+1] + B[i-1])
。Arr[i:i+2] == 2 1
。在这种情况下,我们设置
x = max(x, W[i] + W[i+1] + A[i+1], W[i] + W[i+1] + D[i-1])
。结果x
是我们的答案。这是一个O(N)解决方案。