[R51C] 电脑蓝屏
数据规模:,,,,。
思路
先求出在不玩游戏(游戏负担为 )时,每一秒 电脑所承受的背景负担 。每个进程在第 秒持续贡献 ,这是典型的区间加,用差分数组 求出所有 。
设游戏的恒定负担为 ,则第 秒电脑总负担为 。电脑蓝屏的条件是「总负担 严格大于 性能 」的秒数 至少 为 。也就是说,不蓝屏当且仅当这样的「坏秒数」至多为 。
注意 越大,「坏秒数」越多——这是一个单调关系。把 从小到大排序后,为使坏秒数不超过 ,只需让值最大的 个秒可以坏掉、其余 个秒都不坏。换句话说,排序后第 小的负担(即 ,0-indexed)加上 后仍不能超过 :
因此最大负担就是
若 ,说明即便 (完全不玩游戏)坏秒数也已达到 ,电脑必然蓝屏,输出 -1。
复杂度:时间 (排序为主),空间 。
仓颉实现
import std.console.*
import std.convert.*
import std.sort.*
main(): Int64 {
let reader = Console.stdIn
let first = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p: String => Int64.parse(p) })
let n = first[0]
let m = first[1]
let k = first[2]
let x = first[3]
// 差分数组,1-indexed,大小 n+2
let diff = Array<Int64>(n + 2, { _ => 0 })
var i = Int64(0)
while (i < m) {
let line = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p: String => Int64.parse(p) })
let l = line[0]
let r = line[1]
let a = line[2]
diff[l] += a
diff[r + 1] -= a
i++
}
// 求前缀和得到每秒背景负担 B(t)
let b = Array<Int64>(n, { _ => 0 })
var cur = Int64(0)
var t = Int64(0)
while (t < n) {
cur += diff[t + 1]
b[t] = cur
t++
}
sort(b)
// 排序后第 (n-k+1) 小的负担,0-indexed 为 b[n-k]
let threshold = b[n - k]
let ans = x - threshold
if (ans < 0) {
println(-1)
} else {
println(ans)
}
return 0
}