[R71C] 区间校温
- 难度 入门
- 时限 1s
- 空限 256m
- 枚举前缀最值
思路
先统计初始同步对数量 base。
关键观察:对区间 内部的相邻对 (),两个温度都加 ,同步关系不变;区间外的相邻对也不变。真正可能变化的只有两个边界对:(若 )和 (若 )。
定义左端点贡献与右端点贡献:
即左侧被加 后,边界对 的同步状态变化量:原本差 则变为同步(),原本相等则变为不同步()。
同理是右侧边界对 的变化量。答案即为
直接枚举 是 。由于 与 相互独立,只受 约束,可以扫描右端点 ,同时维护前缀最大值 ,每次用 更新答案即可。
复杂度:时间 ,空间 。
仓颉实现
import std.convert.*
import std.env.*
main() {
let reader = getStdIn()
let n = Int64.parse(reader.readln().getOrThrow())
let a = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p: String => Int64.parse(p) })
var base: Int64 = 0
var i: Int64 = 0
while (i + 1 < n) {
if (a[i] == a[i + 1]) {
base += 1
}
i += 1
}
var maxL: Int64 = 0
var best: Int64 = -2
i = 0
while (i < n) {
if (i >= 1) {
var li: Int64 = 0
if (a[i - 1] == a[i] + 1) {
li = 1
}
if (a[i - 1] == a[i]) {
li -= 1
}
if (li > maxL) {
maxL = li
}
}
var ri: Int64 = 0
if (i + 1 < n) {
if (a[i] == a[i + 1] - 1) {
ri = 1
}
if (a[i] == a[i + 1]) {
ri -= 1
}
}
let cur = maxL + ri
if (cur > best) {
best = cur
}
i += 1
}
println(base + best)
}