洛谷题解——P1102:A-B 数对

题目相关

题目链接

洛谷,https://www.luogu.com.cn/problem/P1102。

我的OJ,http://47.110.135.197/problem.php?id=4759。

题目描述

给出一串数以及一个数字 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。

保证所有输入数据都在 32 位带符号整数范围内。

题目分析

题意分析

在一个数列中,找出所有 A-B=C 的组合。

样例数据分析

有 4 个数据的数列,从中找出所有差值为 1 的数据组合。输入的数列为:1 1 2 3。我们可以知道:

1、第三个数据 2 减去第一个数据 1,两者之差为 1。

2、第三个数据 2 减去第二个数据 1,两者之差为 1。

3、第四个数据 3 减去第三个数据 2,两者之差为 1。

因此总计有 3 组数据。

数据规模分析

1、根据题目描述,保证所有输入数据都在 32 位带符号整数范围内,因此用 int 可以表示。

2、N 的最大范围是 2e5。这个有什么用?只有当数据 A 的总个数和数据 B 的总个数只差为 1 的时候,答案是最大的。就是我们如果有这样一组输入数据:

10 1
1 1 1 1 1 2 2 2 2 2

如果上面的数据,有 5 个 1、5 个 2,这样最后的答案为 5*5=25。

也就是说,我们的输出结果最大的范围是 (n/2)*(n/2),也就是 10^5*10^5=10^10。

说明我们需要用 long long 或者 unsigned long long 来表示结果。

注意:在乘积的过程中,可能导致 int 溢出。

模拟算法

算法思路

1、读入数。

2、统计每个数出现的数量。

3、排序。

4、去重。

5、计算结果。

该算法的核心是如何对所有的数据个数进行统计。

方法一:采用数组来统计,数组的大小是 2^32 个。这个方法明显比较浪费。

方法二:使用 STL 中的 map 来统计。

AC 参考代码

/*
OJ:MYOJ
题号:4759
题目:A-B 数对
地址:http://47.110.135.197/problem.php?id=4759
*/
#include 

const int MAXN = 2e5+2;
int arr[MAXN];

int main() {
    std::map myMap;
    int n;
    int c;
    scanf("%d %d", &n, &c);

    int i;
    for (i=0; i

细节讲解

1、我们必须排序。因为题目没有告诉我们数据是有序的。

2、通过统计个数后,重复的元素就可以删除了。

3、注意计算 ans 的时候,先要将 int 的数据类型强制转换为 unsigned long long,否则两个 int 乘法可能导致溢出。比如输入有 2e5个数据,C 为 1,数列中有 1e5 个 1 和 1e5 个 2。这样我们的答案是 10^5*10^5=10*10,而样例代码中的 map 中保存的是 int 类型,将导致数据溢出。

二分查找

算法思路

1、读入数。

2、排序。

3、从头开始二分查找。我们有了 A 和 C,就可以在数列中查有几个 B。也就是查找数据 B 的左下界和右上界。

AC 参考代码

/*
OJ:MYOJ
题号:4759
题目:A-B 数对
地址:http://47.110.135.197/problem.php?id=4759
*/
#include 

const int MAXN = 2e5+2;
int arr[MAXN];

int main() {
    int n;
    int c;
    scanf("%d %d", &n, &c);

    int i;
    for (i=0; i

 

你可能感兴趣的:(OJ题解,#,洛谷题解)