P1102 A-B 数对
作者:互联网
目录
题目描述
题目描述
出题是一件痛苦的事情!
相同的题目看多了也会有审美疲劳,于是我舍弃了大家所熟悉的 A+B Problem,改用 A-B 了哈哈!
好吧,题目是这样的:给出一串数以及一个数字 CC,要求计算出所有 A - B = CA−B=C 的数对的个数(不同位置的数字一样的数对算不同的数对)。
输入格式
输入共两行。
第一行,两个整数 N, CN,C。
第二行,NN 个整数,作为要求处理的那串数。
输出格式
一行,表示该串数中包含的满足 A - B = CA−B=C 的数对的个数。
输入输出样例
输入 #1复制
4 1 1 1 2 3
输出 #1复制
3
说明/提示
对于 75%75% 的数据,1 \leq N \leq 20001≤N≤2000。
对于 100%100% 的数据,1 \leq N \leq 2 \times 10^51≤N≤2×105。
保证所有输入数据绝对值小于 2^{30}230,且 C \ge 1C≥1。
2017/4/29 新添数据两组
算法求解
分析
-
首先对给的数组a排序
-
然后用b数组记录每个数字及其出现次数(也是按照数字大小排序的)
-
遍历每种数字,对每种数字x,自己的数量是num1,二分查找b中有没有 x + c这个数字,有的话返回其数量num2,没有返回-1
-
那么如果存在x+c,且其数量为num2,则这两种数组成的数对数量为num1 * num2
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
typedef pair<int, int> PII;
typedef long long LL;
const int N = 200010;
int a[N];
vector<PII> b;
int n, c;
int find(int x)
{
int l = 0, r = b.size();
while(l < r)
{
int mid = (r + l) >> 1;
if(b[mid].first >= x) r = mid;
else l = mid+1;
}
if(b[l].first != x) return -1;
else return b[l].second;
}
int main()
{
scanf("%d%d", &n, &c);
for(int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
sort(a, a + n);
int cnt = 0;
for(int i = 0; i < n; i++)
{
if(i && a[i] != a[i-1])
{
b.push_back({a[i-1], cnt});
cnt = 0;
}
cnt++;
}
b.push_back({a[n-1], cnt});
// for(int i = 0; i < b.size(); i++)
// printf("%d %d\n", b[i].first, b[i].second);
LL res = 0;
for(int i = 0; i < b.size(); i++)
{
int t1 = b[i].first;
int num1 = b[i].second;
int t2 = find(t1 + c);
if(t2 != -1)
{
res += (LL)t2 * num1;
}
}
cout << res;
return 0;
}
时间复杂度
\(O(nlogn)\)
参考文章
标签:cnt,题目,P1102,leq,int,数对,++,include 来源: https://www.cnblogs.com/VanHa0101/p/15962925.html