洛谷题单指南-二分查找与二分答案-P1102 A-B 数对
原题链接:https://www.luogu.com.cn/problem/P1102
题意解读:寻找A-B=C的数对数量,C大于0,B一定比A小,枚举B,找A是否存在即可。
解题思路:
先将数据由小到大排序,接下来介绍两种方法:二分、双指针
1、二分
枚举第1~n-1个数,作为B,寻找A=B+C的数量,只需要通过二分查找第一A和最后一个A的位置l、r,数量为r-l+1,进行累加即可。
100分代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
int a[N], n, c;
long long ans;
int bs1(int x)
{
int res;
int l = 1, r = n;
while(l <= r)
{
int mid = (l + r) >> 1;
if(a[mid] >= x) res = mid, r = mid - 1;
else l = mid + 1;
}
if(a[res] == x) return res;
return -1;
}
int bs2(int x)
{
int res;
int l = 1, r = n;
while(l <= r)
{
int mid = (l + r) >> 1;
if(a[mid] <= x) res = mid, l = mid + 1;
else r = mid - 1;
}
if(a[res] == x) return res;
return -1;
}
int main()
{
cin >> n >> c;
for(int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + n + 1);
for(int i = 1; i < n; i++)
{
int A = a[i] + c;
int l = bs1(A), r = bs2(A);
if(l != -1 && r != -1) ans += r - l + 1;
}
cout << ans;
return 0;
}
2、双指针
指针i从1开始所指元素a[i]表示B,指针j从2开始所指元素a[j]表示A,
如果a[j]-a[i]<C,j往后走
如果a[j]-a[i]>C,i往后走
如果a[j]-a[i]=C,计算相同的a[j]、a[i]有多少个,相乘即为当前A-B=C数对的数量,累加即可
100分代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
int a[N], n, c;
long long ans;
int main()
{
cin >> n >> c;
for(int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + n + 1);
for(int i = 1, j = 2; i < n; i++) //双指针,i从1开始,j从2开始,a[i]表示B,a[j]表示A
{
while(a[j] - a[i] < c && j <= n) j++; //如果A-B<C,j往后走
if(a[j] - a[i] == c) //如果A-B=C
{
int cntA = 1, cntB = 1;
while(a[i + 1] == a[i] && i + 1 < n) i++, cntB++; //找B的数量,i移到相同值的最后一个
while(a[j + 1] == a[j] && j + 1 <= n) j++, cntA++; //找A的数量,j移到相同值的最后一个
ans += 1ll * cntA * cntB; //cntA * cntB即当前A-B=C的对数
}
}
cout << ans;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?