题目
给出一串正整数数列以及一个正整数 C C C,要求计算出所有满足 A − B = C A - B = C A−B=C 的数对的个数(不同位置的数字一样的数对算不同的数对)。
输入格式
输入共两行。
第一行,两个正整数 N , C N,C N,C。
第二行, N N N 个正整数,作为要求处理的那串数。
输出格式
一行,表示该串正整数中包含的满足 A − B = C A - B = C A−B=C 的数对的个数。
样例 #1
样例输入 #1
4 1
1 1 2 3
样例输出 #1
3
提示
对于 75 % 75\% 75% 的数据, 1 ≤ N ≤ 2000 1 \leq N \leq 2000 1≤N≤2000。
对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 2 × 1 0 5 1 \leq N \leq 2 \times 10^5 1≤N≤2×105, 0 ≤ a i < 2 30 0 \leq a_i <2^{30} 0≤ai<230, 1 ≤ C < 2 30 1 \leq C < 2^{30} 1≤C<230。
2017/4/29 新添数据两组
解析
使用二分搜索,对每个 A A A 搜索对应的 B B B 的个数即可。
具体做法是:先求出 B B B 的值,然后用二分找出 B B B… 的开始位置和结束位置,相减就得到了 B B B 的个数。
注意
- 题目并没有说数列是否已排序,所以需要先排序
- 输入数据的范围最大是 2 30 2^{30} 230,相当于
int64
或long long
或double
- 输出的结果个数可能超出
int
范围,应当使用long long
代码
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
#include <stdlib.h>
#define MAXN 200000
double arr[MAXN];int cmpfunc(const void *a, const void *b) {double arg1 = *(const double*)a;double arg2 = *(const double*)b;if (arg1 < arg2) return -1;if (arg1 > arg2) return 1;return 0;
}int main()
{int n;double c;scanf("%d%lf", &n, &c);for (int i = 0; i < n; i++){scanf("%lf", &arr[i]);}qsort(arr, n, sizeof(double), cmpfunc);long long count = 0;for (long long i = 0; i < n; i++){long long lower = 0, upper = 0;double a = arr[i];double b = a - c;// 找下限long long l = 0, r = i;while (l < r){long long mid = (l + r) / 2;if (arr[mid] >= b)// [l,r]->[l,mid]r = mid;else// [l,r]->[]l = mid + 1;}if (arr[l] != b)continue;elselower = l;//printf("%d\n", lower);// 找上限l = 0, r = i;while (l < r){long long mid = (l + r + 1) / 2;if (arr[mid] <= b)// [l,r]->[l,mid]l = mid;else// [l,r]->[]r = mid - 1;}upper = l;//printf("%d\n", l);count += upper - lower + 1;}printf("%lld\n", count);return 0;
}