二分算法实战:A-B 数对与高考志愿问题解析
二分查找是算法竞赛和工程实践中非常基础且高效的技术。本文将通过两道经典例题——A-B 数对与烦恼的高考志愿,深入讲解二分查找的核心思想、STL 函数的灵活运用以及手动实现时的边界处理技巧。
一、A-B 数对
1.1 题目背景
给定一个整数数组和一个常数 C,求满足 A - B = C 的数对 (A, B) 的数量。

1.2 解题思路
由于顺序不影响最终结果,我们可以先将整个数组排序。由公式 A - B = C 可推导出 B = A - C。因为 C 是已知的,我们可以枚举每一个 A,然后在数组中快速查找有多少个 B 满足条件。
这里的关键在于如何高效统计 B 的数量。利用 STL 中的 lower_bound 和 upper_bound 函数可以完美解决:
- lower_bound:返回区间内第一个大于等于目标值 k 的位置(左闭右开区间)。
- upper_bound:返回区间内第一个大于目标值 k 的位置。
两个指针相减,即为区间内等于 k 的元素个数。
例如数组 a = [10, 20, 20, 20, 30, 40],查询 20:
lower_bound返回第一个 20 的位置。upper_bound返回最后一个 20 之后的位置。- 两者之差即为 20 出现的次数。

需要注意的是,STL 二分函数仅适用于有序序列。如果数组无序,必须先排序。当然,二分算法的本质是寻找'二段性',只要数据具备单调性或二段性,即使不使用 STL,手动实现也是可行的。
1.3 代码实现
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const N = + ;
LL a[N];
{
n, c;
cin >> n >> c;
( i = ; i <= n; i++) cin >> a[i];
(a + , a + + n);
LL ret = ;
( i = ; i <= n; i++) {
LL b = a[i] - c;
ret += (a + , a + i + , b) - (a + , a + + i, b);
}
cout << ret << endl;
;
}




