题目背景
出题是一件痛苦的事情!
相同的题目看多了也会有审美疲劳,于是我舍弃了大家所熟悉的 A+B Problem,改用 A-B 了哈哈!
题目描述
给出一串正整数数列以及一个正整数 C,要求计算出所有满足A−B=C 的数对的个数(不同位置的数字一样的数对算不同的数对)。
输入格式
输入共两行。
第一行,两个正整数 N,C。
第二行,N 个正整数,作为要求处理的那串数。
输出格式
一行,表示该串正整数中包含的满足 A−B=C 的数对的个数。
输入输出样例
输入
4 1 1 1 2 3
输出
3
说明/提示
对于 75% 的数据,1≤N≤2000。
对于 100% 的数据,1≤N≤2×10^5,0≤ai<2^30,1≤C<2^30。
2017/4/29 新添数据两组
思路:
这个题需要我们思维转变一下,A-B=C 可以 转换成 A = B + C,C是固定的,我们只需要枚举B就可以,这样就相当于我们有两个固定的值,然后去找A就行,从求数对,变成求A的个数(右边界 - 左边界),当然找到的找个第一个A也要算的答案里,要 ans++ 一下,感觉会更简单一些,以上是本人综合大佬的博客和自己的理解所写,如有错误请点出~
代码思路:
因为我们希望找到第一个A,所以先用左模板,去找到第一个A,后面希望找到最后一个A,所以我们直接使用右模板即可,注意变量的定义。
AC代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 2e5+10;
int a[N];
int n,c;
int main()
{
long long ans = 0;
scanf("%d %d",&n,&c);
for(int i = 0;i<n;i++) cin >> a[i];
sort(a,a+n);
//C = A - B,A = B + C
for(int i=0;i<n;i++)
{
int x = a[i] + c;
int l=0,r=n-1;
while(l < r)
{
int mid = l + r >> 1;
if(a[mid]>=x) r = mid;
else l = mid + 1;
}
if(a[l] == x)
{
//找到左面的一个答案要+1
ans++;
int ll=l,r=n-1;
while(ll < r)
{
int mid = ll + r + 1 >> 1;
if(a[mid] <= x) ll = mid;
else r = mid - 1;
}
//区间 = 右边界 - 左边界
ans = ans + ll - l;
}
}
cout << ans << endl;
return 0;
}