[R64C] 盆栽
- 难度 普及
- 时限 1s
- 空限 512m
- 模拟
数据规模:,, 且严格递增,,。
思路
每盆盆栽之间互不影响,可以对每盆单独维护它最近一次被处理后的状态。设:
- 表示第 盆在最近一次处理后的水分;
- 表示第 盆最近一次被处理的时刻。
初始时 ,。
当时刻 发生关于第 盆的事件时,先结算从 到 的自然蒸发:
然后令 。接下来根据事件类型处理:
- 若为
1 t x v,浇水后令 ; - 若为
2 t x,当前答案就是 。
虽然所有事件时间整体递增,但同一盆不一定每次都出现,所以必须为每盆分别记录 ,不能只维护一个全局时间。
复杂度:时间 ,空间 。
仓颉实现
import std.env.*
import std.convert.*
main(): Int64 {
let reader = getStdIn()
let firstLine = reader.readln().getOrThrow().split(" ", removeEmpty: true)
let n = Int64.parse(firstLine[0])
let q = Int64.parse(firstLine[1])
let a = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p => Int64.parse(p) })
// val[x] 最近一次处理后的水分,last[x] 最近一次处理的时刻
let val = Array<Int64>(n, { i => a[i] })
let last = Array<Int64>(n, { _ => 0 })
let sb = StringBuilder()
for (_ in 0..q) {
let parts = reader.readln().getOrThrow().split(" ", removeEmpty: true)
let op = Int64.parse(parts[0])
let t = Int64.parse(parts[1])
let x = Int64.parse(parts[2])
let xi = x - 1
// 结算从 last[x] 到 t 的自然蒸发
let cur = if (val[xi] - (t - last[xi]) > 0) { val[xi] - (t - last[xi]) } else { 0 }
val[xi] = cur
last[xi] = t
if (op == 1) {
let v = Int64.parse(parts[3])
val[xi] = val[xi] + v
} else {
sb.append("${val[xi]}\n")
}
}
print(sb.toString())
return 0
}
要点:
- 蒸发结算只与「该盆上次被处理的时刻」有关,与全局时间无关,因此查询和浇水都要先结算蒸发再更新 。
- 蒸发量不会让水分降到负数,用
if-else表达式取 。 - 多次浇水后水分可达 量级(、、),需要用
Int64。 - 输出量大,用
StringBuilder一次性拼接所有查询答案。