【ETOJ P1004】两数之和 题解(排序+双指针+upper_bound)

63 阅读1分钟

题目描述

给定一个大小为 nn 的数组 aa 和一个整数 mm,求其中有多少对二元组 (ai,aj)(a_i, a_j) 满足:

  • 1i<jn1 \leq i < j \leq n
  • ai+aj>ma_i + a_j > m

输入格式

第一行两个整数 n,mn, m,意义如上。 (1n2×105,1m109)(1 \leq n \leq 2 \times 10^5, 1 \leq m \leq 10^9)

第二行 nn 个整数,第 ii 个整数表示 aia_i(0ai109)(0 \leq a_i \leq 10^9)

输出格式

一个数字,表示满足条件的二元组的个数。

输入样例

3 5
2 3 4

输出样例

2

提示

样例中满足条件的二元组为 (2,4)(2, 4), (3,4)(3, 4)


思路

首先,从输入中读取数组的大小nn和目标值mm,然后读取nn个数组元素。对读取的数组元素进行排序,方便后续使用双指针进行查找。

然后,遍历排序后的数组。对于每个元素a[j]a[j],使用upper_bound函数找到第一个大于ma[j]m - a[j]的元素的位置ii。这是因为按照题目要求,需要找出所有a[i]+a[j]>ma[i] + a[j] > m的二元组,而数组已经排序,所以对于当前的a[j]a[j],所有在它之前且小于或等于ma[j]m - a[j]a[i]a[i]都能与a[j]a[j]组成满足条件的二元组。

最后,对于每个jj,都将满足条件的二元组数量jij - i累加到答案中。这是因为从iij1j - 1的所有元素都可以与a[j]a[j]组成满足条件的二元组。


AC代码

#include <algorithm>
#include <iostream>
#define AUTHOR "HEX9CF"
using namespace std;
using ll = long long;

const int N = 1e6 + 7;

int n, m;
int a[N];

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	sort(a + 1, a + n + 1);

	ll ans = 0;
	for (int j = 1; j <= n; j++) {
		// 寻找第一个a[i] > m - a[j]
		int i = upper_bound(a + 1, a + j, m - a[j]) - a;
		// 从i到j - 1都的a[i]符合条件
		ans += j - i;
	}
	cout << ans << endl;
	return 0;
}