[R13D] 支架
- 难度 普及-
- 时限 1s
- 空限 512m
- 贪心排序
数据规模:,,。
思路
每个支架由两根木棍组成,承载重量是两根木棍长度的乘积; 个支架要放同样重的物品,所以答案等于 个支架承载重量的最小值。要让这个最小值尽量大,本质是把 根木棍两两配对,使所有「配对乘积的最小值」最大化。
直觉上,把最长的那根和最短的那根配在一起会很浪费——乘积被短板拖垮。正确的贪心策略是:将 根木棍长度从大到小排序后,只用最长的 根,让第 根和第 根配对,第 根和第 根配对……第 个支架用 和 。于是答案就是:
简单理解:每对都由「较大的前段」和「较小的后段」配成,配对方式固定为对应位置,乘积序列里最弱的一个就是整个方案的瓶颈。任何把两根大棍或两根小棍配到一起的方案,都会让另一对变小、从而拉低最小值,因此这种首尾配对是最优的。
复杂度:排序 ,枚举 。
仓颉实现
import std.env.*
import std.convert.*
import std.sort.*
main(): Int64 {
let reader = getStdIn()
let first = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p => Int64.parse(p) })
let n = first[0]
let m = first[1]
let a = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p => Int64.parse(p) })
sort(a, descending: true)
let mm = m
var ans: Int64 = a[0] * a[2 * mm - 1]
var i = 1
while (i < mm) {
let prod = a[i] * a[2 * mm - 1 - i]
if (prod < ans) {
ans = prod
}
i = i + 1
}
println(ans)
return 0
}
要点:
- 把
m复制成不可变的mm再在 lambda 外的下标表达式里使用,避免可变变量在闭包/表达式中的限制。 - 用
std.sort的全局函数sort(a, descending: true)原地从大到小排序, 时在 下仍能稳定跑进 1 秒。 - 乘积最大 ,超出
Int32但远在Int64范围内,直接用Int64计算即可。