洛谷 A-B数对(总结各位大佬的方法)

A-B 数对

题目背景

出题是一件痛苦的事情!

相同的题目看多了也会有审美疲劳,于是我舍弃了大家所熟悉的 A+B Problem,改用 A-B 了哈哈!

题目描述

给出一串正整数数列以及一个正整数 C C C,要求计算出所有满足 A − B = C A - B = C AB=C 的数对的个数(不同位置的数字一样的数对算不同的数对)。

输入格式

输入共两行。

第一行,两个正整数 N , C N,C N,C

第二行, N N N 个正整数,作为要求处理的那串数。

输出格式

一行,表示该串正整数中包含的满足 A − B = C A - B = C AB=C 的数对的个数。

样例 #1

样例输入 #1

4 1
1 1 2 3

样例输出 #1

3

提示

对于 75 % 75\% 75% 的数据, 1 ≤ N ≤ 2000 1 \leq N \leq 2000 1N2000

对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 2 × 1 0 5 1 \leq N \leq 2 \times 10^5 1N2×105 0 ≤ a i < 2 30 0 \leq a_i <2^{30} 0ai<230, 1 ≤ C < 2 30 1 \leq C < 2^{30} 1C<230

题解

这个题可以用二分,也可以用映射来解决
用映射解决:
我们知道要想出现A-B=C
我们可以在原数组中全部减去一个C,最后找到与原数组有重复数字以及他们的次数即可

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;

ll a[N];
ll n,m;
ll ans;
map<ll,ll> b;
//A-B=C,我们用a数组存储我们一开始所得到的值,之后我们可以将每个值都减去一个c,如果最后有重复的,
//我们就可以统计他在原数组所在的长度
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		b[a[i]]++;
		a[i]-=m;
	}
	for(int i=1;i<=n;i++){
		ans+=b[a[i]];
	}
	cout<<ans<<endl;
	return 0;
	
}

用二分解决:

#include<bits/stdc++.h>

using namespace std;

int n,c;
int a[200005];

int bsearchleft(int key)
{
    int l = 1;
    int r = n+1;
    while(l<r){
        int mid = l+(r-l)/2;
        if(a[mid]==key)
            r = mid;
        else if(a[mid]<key)
            l = mid+1;
        else if(a[mid]>key)
            r = mid;
    }
    return a[l]==key?l:0;
}

int bsearchright(int key)
{
    int l = 1;
    int r = n+1;
    while(l<r){
        int mid = l+(r-l)/2;
        if(a[mid]==key)
            l = mid+1;
        else if(a[mid]<key)
            l = mid+1;
        else if(a[mid]>key)
            r = mid;
    }
    return a[l-1]==key?l-1:0;
}

int main()
{
    cin >> n >> c;
    for(int i = 1; i <= n; ++i)
        cin >> a[i];
    sort(a+1,a+1+n);
    long long ans = 0;
    for(int i = 1; i <= n; ++i){
        int key = a[i]-c;
//在返回非0的情况下,需要 ans+=(右边界-左边界+1);
        int sum = (bsearchright(key)&&bsearchleft(key));
        if(sum)
            sum = (bsearchright(key)-bsearchleft(key)+1);;
        ans += sum;
    }
    cout << ans << endl;
    return 0;
}

双指针做法:

#include<bits/stdc++.h>

using namespace std;

int n,c;
int a[200005];

int main()
{
    cin >> n >> c;
    for(int i = 1; i <= n; ++i)
        cin >> a[i];
    sort(a+1,a+1+n);
    long long ans = 0;
    int r1 = 1;
    int r2 = 1;
    for(int l = 1; l <= n; ++l){
        while(r1<=n&&a[r1]-a[l]<c)
            ++r1;
        while(r2<=n&&a[r2]-a[l]<=c)
            ++r2;
        if(a[r1]-a[l]==c&&a[r2-1]-a[l]==c)
            ans += r2-r1;
    }
    cout << ans << endl;
    return 0;
}

posted @ 2023-05-24 21:04  du463  阅读(154)  评论(0编辑  收藏  举报  来源