二分算法实战:A-B 数对与高考志愿问题解析
二分查找是算法竞赛中的高频考点,核心在于利用数据的有序性或二段性快速定位目标。本文将通过 A-B 数对与烦恼的高考志愿两道经典例题,系统讲解从排序预处理到边界处理的完整思路。
A-B 数对
题目描述
给定一个整数数组和一个常数 C,求满足 A - B = C 的数对 (A, B) 的数量。顺序不影响结果。
解题思路
方程可变形为 B = A - C。由于 C 已知,我们可以枚举所有的 A,然后在数组中查找是否存在对应的 B。为了高效统计,先将数组排序。利用二分查找可以快速确定值为 B 的元素区间长度。
这里涉及两个 STL 函数:
lower_bound:返回第一个大于等于 k 的位置。upper_bound:返回第一个大于 k 的位置。
两者相减即为值等于 k 的元素个数。注意 ST L 函数要求序列有序,且区间为左闭右开。
代码实现
#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 的区间
// lower_bound 找 >= b 的第一个位置
// upper_bound 找 > b 的第一个位置
ret += upper_bound(a + 1, a + i + , b) - (a + , a + + i, b);
}
cout << ret << endl;
;
}


