[R16C] 三元组2
- 难度 普及/提高-
- 时限 1s
- 空限 512m
- 枚举
数据规模:,。
思路
题面要求统计满足 且 的三元组数量。关键观察是判定条件只与 、 有关,与 及 无关。
对条件做等价变形。不妨设 ,则 、,代入得 ,即 。综合两种大小关系,原条件等价于
因此只要固定一对满足条件的 ,所有夹在中间的下标 ()都合法,这样的 共有 个。于是只需两重循环枚举 ,满足条件就把 累加进答案。
复杂度:时间 ,空间 。三元组数量最多约 ,答案必须用 Int64 累加。
仓颉实现
import std.env.*
import std.convert.*
main(): Int64 {
let reader = getStdIn()
let n = Int64.parse(reader.readln().getOrThrow())
let a = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p => Int64.parse(p) })
var ans: Int64 = 0
var i = 0
while (i < n - 1) {
let ai = a[i]
var k = i + 1
while (k < n) {
let ak = a[k]
// 等价于 max(ai, ak) >= 2 * min(ai, ak)
let lo = if (ai < ak) { ai } else { ak }
let hi = if (ai < ak) { ak } else { ai }
if (hi >= lo * 2) {
ans = ans + (k - i - 1)
}
k = k + 1
}
i = i + 1
}
println(ans)
return 0
}
要点:
- 条件化简:把含绝对值和
min的条件归约为 ,消除分支判断,只需一次比较。 - 降维:注意到条件与 无关后,把 的三重循环压缩成 的双重循环,每对合法 贡献 个 。
- 避免溢出:, 最大 在
Int64范围内;答案最大约 ,累加器用Int64。