上链接:A-B 数对 - 洛谷
上题干:
题目描述
给出一串正整数数列以及一个正整数 C,要求计算出所有满足 A−B=C 的数对的个数(不同位置的数字一样的数对算不同的数对)。
输入格式
输入共两行。
第一行,两个正整数 N,C。
第二行,N 个正整数,作为要求处理的那串数。
输出格式
一行,表示该串正整数中包含的满足 A−B=C 的数对的个数。
输入输出样例
输入 #1
4 1 1 1 2 3输出 #1
3说明/提示
对于 75%75% 的数据,1≤N≤2000。
对于 100%100% 的数据,1≤N≤2×10^5,0≤ai<2^30,1≤C<2^30。
2017/4/29 新添数据两组
先讲一下这题的思路:
C是被给出的,A,B是在数列中找。因为 A=B+C 所以我们只需要遍历A,B其中的一个就好了。
例如我们想遍历A ,所以我们只需要判断B是否存在,B存在几个就记录几个答案就行了。
(当然了,我们要事先排好序)
因为我们事先排好了序,所以如果B存在,我们只需要找到B的左右边界,再相减就可以了。
这道题有两种方法:
二分法,求左右边界 或者用lower_bound和upper_bound 求左右边界
#include <iostream>
using namespace std;
const int N=2e5+10;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
long long int a[N];
int main(int argc, char** argv) {
long long n,c;
cin>>n>>c;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
sort(a+1,a+n+1);
long long sum=0;
for(int i=1;i<=n;i++)
{
lower_bound(a+1,a+1+n,a[i]+c);
upper_bound(a+1,a+1+n,a[i]+c);
sum+=upper_bound(a+1,a+1+n,a[i]+c)- lower_bound(a+1,a+1+n,a[i]+c);
}
cout<<sum;
return 0;
}
第二种方法就是双指针算法来维护这一段B的区间:
怎么实现代码呢?
我们先定义两个指针 l,r=0;
从i=1开始遍历整个数组,l指向的是第一个等于a[i]+c的数(a[l]<a[i]+c),r指向的是第一个大于a[i]+c的数(a[r]<a[i]+c),
如果这个B存在,r-l就是B的个数
如果这个B不存在,那么l,r都会指向第一个大于B的数。即l,r重合了,即B的个数位r-l=0;
using namespace std;
const int N = 2e5 + 10;
long long int a[N];
int main()
{
long long n, c;
cin >> n >> c;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
sort(a + 1, a + 1 + n);
int l = 0, r = 0;
long long sum = 0;
for (int i = 1; i <= n; i++)
{
while (l <= n and a[l] < a[i] + c)l++;
while (r <= n and a[r] <= a[i] + c)r++;
sum += r - l;
}
cout << sum;
}