[R75C] 站点
数据规模:,,。
思路
设通道 对应站点 与 之间的边。任务 走过的路程是 ,记所有任务的这段路程之和为 。
若把传送门建在通道 ,那么只有经过这条通道的任务才会省下 :任务 经过通道 当且仅当 。设 为经过通道 的任务数,则总路程从 减少到 。
于是答案就是
用前缀和求出:预处理 (),则单个任务贡献 。
用差分求出:对每个任务 ,它覆盖通道区间 ,在差分数组上做 d[l] += 1、d[r] -= 1,最后对 做前缀和,得到的就是 。
注意 最大可达 ,需要用 64 位整数。
复杂度
时间 ,空间 。
仓颉实现
查看仓颉实现
import std.env.*
import std.convert.*
main() {
let reader = getStdIn()
let first = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p: String => Int64.parse(p) })
let n = first[0]
let q = first[1]
let w = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p: String => Int64.parse(p) })
let pre = Array<Int64>(n, { _ => 0 })
var s: Int64 = 0
for (i in 0..(n - 1)) {
s += w[i]
pre[i + 1] = s
}
let diff = Array<Int64>(n + 1, { _ => 0 })
var total: Int64 = 0
for (_ in 0..q) {
let lr = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p: String => Int64.parse(p) })
let l = lr[0]
let r = lr[1]
total += pre[r - 1] - pre[l - 1]
diff[l] += 1
diff[r] -= 1
}
var best: Int64 = 0
var cur: Int64 = 0
for (i in 1..n) {
cur += diff[i]
let gain = w[i - 1] * cur
if (gain > best) {
best = gain
}
}
println(total - best)
}