二分算法实战:A-B 数对与高考志愿问题解析
一、A-B 数对
1.1 题目描述
给定一个整数序列,求满足 A - B = C 的数对 (A, B) 的数量。其中 C 为给定常数。
1.2 算法思路
既然加法交换律成立,顺序其实不重要。为了利用二分的高效性,我们首选将数组排序。
核心逻辑很简单:已知 A 和 C,求满足 A - B = C 的 B 的数量,等价于找有多少个 B 等于 A - C。
由于数组已排序,我们可以枚举每一个 A,然后在前面部分查找值等于 A - C 的元素个数。这里正好可以用二分快速查找出区间的长度。
STL 辅助函数:
lower_bound:返回区间中第一个大于等于 k 的位置(左闭右开区间)。upper_bound:返回区间中第一个大于 k 的位置。
两个指针相减,就是包含目标值这个数区间的长度。
注意:STL 的使用范围很「局限」,查询「有序序列」的时候才有用,数组无序的时候就无法使用。但是我们的二分算法也能在「数组无序」的时候使用,只要有「二段性」即可。
1.3 代码实现
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
LL a[N];
int main() {
int n, c;
cin >> n >> c;
for (int i = 1; i <= n; i++) cin >> a[i];
// 排序是二分的前提
sort(a + 1, a + 1 + n);
LL ret = 0;
for (int i = 2; i <= n; i++) {
LL b = a[i] - c;
// 统计 [1, i] 范围内值为 b 的元素个数
ret += upper_bound(a + 1, a + i + , b) - (a + , a + + i, b);
}
cout << ret << endl;
;
}


