[R4D] 排队问题
- 难度 入门
- 时限 1s
- 空限 512m
- 排序前缀和
思路
名同学都问问题时,按 从小到大排队可使等待时间总和最小。设按该顺序第 名同学( 开始编号)前面的同学的所需时间之和为 ,全部同学的总等待时间为 。
若去掉排在第 名的同学 :他的等待时间 被减去;排在他后面的 名同学每人等待时间都减少 。因此答案为
所需时间相同的同学互换位置不影响上式结果,所以按值排序后任意同名次的同学直接套用公式即可。
复杂度:时间 ,空间 。
仓颉实现
import std.convert.*
import std.env.*
import std.sort.*
func solve() {
let reader = getStdIn()
let n = Int64.parse(reader.readln().getOrThrow())
let nn = n
let a = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p => Int64.parse(p) })
let order = Array<Int64>(nn, { i => i })
sort(order, key: { i => a[i] })
let pos = Array<Int64>(nn, { _ => 0 })
let wait = Array<Int64>(nn, { _ => 0 })
var pre: Int64 = 0
for (j in 0..nn) {
pos[order[j]] = j
wait[j] = pre
pre += a[order[j]]
}
var total: Int64 = 0
for (j in 0..nn) {
total += wait[j]
}
let sb = StringBuilder()
for (i in 0..nn) {
let j = pos[i]
sb.append(total - wait[j] - a[i] * (n - 1 - j))
sb.append("\n")
}
print(sb.toString())
}
main() {
solve()
}