CF1733D2 Zero-One (Hard Version) 题解
提示 1
首先统计
提示 2
分类讨论:
提示 3
设
- 如果
m=2 且p[0]+1=p[1] ,则答案为\min(2y, x) ,因为可以找个不相邻的位置充当「中转站」(注意n\ge 5 ); - 否则答案为
m/2 \cdot y ,方案是把p[i] 和p[i+m/2] 一组。
提示 4
对于
提示 5
设
- 找个不相邻的位置操作,花费
y ,那么对于p[i] 相当于花费y/2 ,因此f[i] = f[i-1] + y/2 - 不断找相邻的位置操作,把
p[i] 和p[i-1] 一组,那么需要操作p[i]-p[i-1] 次,因此f[i] = f[i-2] + (p[i]-p[i-1])\cdot x
两者取最小值,即
初始值
代码实现时,为了方便处理
此外,计算
答疑
问:为什么花费
答:因为
问:转移方程没有对选了多少个
答:注意
代码(Golang)
package main
import("bufio";."fmt";"os")
func main() {
in := bufio.NewReader(os.Stdin)
out := bufio.NewWriter(os.Stdout)
defer out.Flush()
var T, x, y int64
var a, b []byte
for Fscan(in, &T); T > 0; T-- {
Fscan(in, &a, &x, &y, &a, &b)
p := []int{}
for i, c := range a {
if c != b[i] {
p = append(p, i)
}
}
m := len(p)
if m%2 > 0 {
Fprintln(out, -1)
} else if m == 0 || y <= x {
if m == 2 && p[0]+1 == p[1] {
Fprintln(out, min(y*2, x))
} else {
Fprintln(out, int64(m/2)*y)
}
} else {
f, g := int64(0), y
for i := 1; i < m; i++ {
f, g = g, min(g+y, f+int64(p[i]-p[i-1])*x*2)
}
Fprintln(out, g/2)
}
}
}
func min(a, b int64) int64 { if a > b { return b }; return a }
复杂度分析
- 时间复杂度:
O(n) 。 - 空间复杂度:
O(n) 。