C++:洛谷 P1102 A-B 数对

一·题目描述:

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

输入共两行。
第一行,两个正整数 N,CN,C。

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

输出格式

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

输入输出样例
输入 #1

4 1
1 1 2 3

输出 #1

3

二.思路分析:

由于我们要计算出所有满足 A - B = C 的数对的个数,所以转换为找到值为A - C 的个数,可以先对数组排序,用二分查找找到第一个数到当前这个数前面的一个数区间内的A - C,由于A - C在当前区间内的个数不唯一,因此两次二分查找分别找到左边第一次出现的位置和右边第一次出现的位置,他们的下标之差加1即为当前区间A - C的个数,依次遍历每个区间即可求得所有值为A - C的个数,即所有满足A - B = C的数对的个数。

三.代码示例:

时间复杂度O(nlogn)

#include 

using namespace std;

typedef long long LL;

const int N = 1e6 + 10;
LL q[N];
LL res; //答案会爆int

int main()
{
    int n, m;
    cin >> n >> m;
    for(int i = 0 ; i < n ; i++) scanf("%lld",&q[i]);
    sort(q, q + n);
    
    for(int i = 0 ; i < n ; i++)
    {
        int x = q[i];
        int l = 0, r = i - 1;
        if(q[i] > m)
        {
            while(l < r)
            {
                int mid = l + r >> 1;
                if(q[mid] >= x - m) r = mid;
                else l = mid + 1;
            }
            int t = l; //找到区间内左边第一次出现的下标
            l = 0, r = i - 1;
            while(l < r)
            {
                int mid = l + r + 1 >> 1;
                if(q[mid] <= x - m) l = mid;
                else r = mid - 1;
            }
             //找到区间内右边第一次出现的下标
            if(x - q[t] == m && x - q[l] == m) 
            {
                res += l - t + 1;
            }
        }
    }
    cout << res;
    return 0;
}

你可能感兴趣的:(杂题题解,c++,算法,数据结构)