洛谷 A-B数对(总结各位大佬的方法)
A-B 数对
题目背景
出题是一件痛苦的事情!
相同的题目看多了也会有审美疲劳,于是我舍弃了大家所熟悉的 A+B Problem,改用 A-B 了哈哈!
题目描述
给出一串正整数数列以及一个正整数 C C C,要求计算出所有满足 A − B = C A - B = C A−B=C 的数对的个数(不同位置的数字一样的数对算不同的数对)。
输入格式
输入共两行。
第一行,两个正整数 N , C N,C N,C。
第二行, N N N 个正整数,作为要求处理的那串数。
输出格式
一行,表示该串正整数中包含的满足 A − B = C A - B = C A−B=C 的数对的个数。
样例 #1
样例输入 #1
4 1
1 1 2 3
样例输出 #1
3
提示
对于 75 % 75\% 75% 的数据, 1 ≤ N ≤ 2000 1 \leq N \leq 2000 1≤N≤2000。
对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 2 × 1 0 5 1 \leq N \leq 2 \times 10^5 1≤N≤2×105, 0 ≤ a i < 2 30 0 \leq a_i <2^{30} 0≤ai<230, 1 ≤ C < 2 30 1 \leq C < 2^{30} 1≤C<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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?