数矩形二分做法的题解

image

看到这道题,很容易想到枚举 x,再去找 y,这样一个暴力代码就诞生了,这样会超时,所以我们就来介绍一下二分做法:

问题转换

对于每对垂直线段 a[i]a[j](i < j),水平距离 s = a[j] - a[i]

垂直距离 d 需满足 |s - d| = k,即 d = s + kd = s - k

每个有效 d 对应的点对数为 m - d + 1

核心公式

对于 d = s + k,有效 a[i] 范围为 [max(1, a[j] + k - m), a[j] + k - 1]

对于 d = s - k,有效 a[i] 范围为 [max(1, a[j] - k - m), a[j] - k - 1]

优化策略

使用前缀和数组 s 快速计算范围内 a[i] 的总和。

二分查找确定有效 a[i] 的范围,避免遍历所有可能的 i

实现细节

数组索引

采用 0-based-1 索引( a[0] 到 a[n-1] ),前缀和数组 s 同步调整。

前缀和 s[i] 表示 a[0] 到 a[i-1] 的和。

二分查找

lower_{}bound(a , a + j, L) 返回第一个 >= L 的位置。

upper_{}bound(a , a + j, R) 返回第一个 >R 的位置,需减 1 得到最后一个 <= R 的位置。

条件判断

对于每个 j,检查 L1 <= R1 L2 <= R2 确保范围有效。

使用 itl <= itr 验证二分查找结果是否构成有效区间。

贡献计算

对于每个有效范围 [itl, itr],总和为 $s[itr + 1] - s[itl](前缀和)加上固定贡献 (m - a[j] ± k + 1) * (itr - itl + 1)$。

复杂度分析

  • 时间复杂度O (nlogn)
    • 遍历每个 j 需要 O(n)
    • 每次遍历中,二分查找和前缀和计算为 O(log n)

核心逻辑总结

  1. 枚举线段:对于每个线段 j,考虑所有 i<j
  2. 计算范围:根据 d=s+kd=s−k 分别确定 a[i] ​ 的有效范围。
  3. 二分查找:快速定位有效 i 的区间,避免遍历所有可能的 i。
  4. 前缀和优化:利用前缀和数组快速计算区间和,减少时间复杂度。

该算法通过数学推导和预处理,将时间复杂度从 O(n^2) 优化至 O(nlogn),适用于大规模数据。

这样这道题就做完了。
完结撒花 ✿✿ヽ(°▽°)ノ✿

7 个赞

不错,赞了

建议使用markdown和 \LaTeX

谢谢~~~

1 个赞

好的好的

1 个赞

改完了

厉害厉害%%%%%%%%(送花)

太牛了

呜呜呜,为什么没有人给我的题解点赞 qwq

1 个赞

你的题解在哪里? @我命由我不由天

@冯俊骁 关于模考 T2 - 常规 - 信友队论坛 (xinyoudui.com)

啊?那个我不是已经点赞了吗?

e我不知道哇

e赞比较少(

你会上X-camp英文论坛吗

会呀

啊你读得懂英文?

看这个
局部截取_20250715_163614

我当然读得懂英文啦

太nb了