P1102 A-B 数对

A-B 数对

题目描述

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

输入格式

输入共两行。

第一行,两个正整数 \(N,C\)

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

输出格式

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

样例 #1

样例输入 #1

4 1
1 1 2 3

样例输出 #1

3

提示

对于 \(75\%\) 的数据,\(1 \leq N \leq 2000\)

对于 \(100\%\) 的数据,\(1 \leq N \leq 2 \times 10^5\)\(0 \leq a_i <2^{30}\),\(1 \leq C < 2^{30}\)

分析

  • 已知 \(C\),可以使用双重循环枚举 \(A,B\),复杂度 \(O(n^2)\),这样会超时.
  • 那么这样的问题,考虑标记某个数出现次数,可以优化到 \(O(n)\).
  • 也可以使用下标距离的方式,对元素排序,利用下标差值确定元素个数,复杂度 \(O(nlogn)\).
  • 注意开 \(long long\),同时由于数据 \(2^{30}\),需要使用 \(map\) 映射。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e6+10, INF=0x3f3f3f3f;
int a[N],n,A,B,C;
map<LL,LL> mp;
LL ans=0;

void slove1() {
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=n; j++) {
            if(i!=j && a[i]-a[j]==C) {
                ans++;
            }
        }
    }
}
void slove2() {
    for(int i=1; i<=n; i++) mp[a[i]]++;
    for(int i=1; i<=n; i++) {
        int A=a[i], B=a[i]-C;
        ans += mp[B];
    }
}
void slove3() {
    sort(a+1, a+1+n);
    for(int i=1; i<=n; i++) {
        int A=a[i], B=a[i]-C;
        int l=lower_bound(a+1, a+1+n, B)-a;
        int r=upper_bound(a+1, a+1+n, B)-a;
        ans += r-l;
    }
}
int main() {
//    freopen("data.in", "r", stdin);
    cin>>n>>C;
    for(int i=1; i<=n; i++) cin>>a[i];
    slove2();
    cout<<ans<<endl;
    return 0;
}
posted @ 2022-10-09 16:10  HelloHeBin  阅读(220)  评论(0)    收藏  举报