【双指针/二分】P1102 A-B 数对

P1102 A-B 数对

题目描述

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

输入格式

输入共两行。

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

第二行,第 iii 个数为 aia_iai,数字之间用一个空格隔开,共 NNN 个正整数,作为要求处理的那串数。

输出格式

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

输入输出样例 #1

输入 #1

复制代码
4 1
1 1 2 3

输出 #1

复制代码
3

说明/提示

对于 100%100\%100% 的数据,1≤N≤2×1051 \leq N \leq 2 \times 10^51≤N≤2×105,0≤ai<2300 \leq a_i <2^{30}0≤ai<230,1≤C<2301 \leq C < 2^{30}1≤C<230。


暴力做法

先排序,然后再挨个遍历即可。

得分 76pts76pts76pts,时间超限。

cpp 复制代码
#include<bits/stdc++.h>
#define int long long
using namespace std;

bool cmp(int a,int b) {return a<b;}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	
	int n,c,answer=0;
	cin>>n>>c;
	int a[n];
	for(int i=0;i<n;i++)
		cin>>a[i];
	sort(a,a+n,cmp);
	for(int i=n-1;i>=0;i--) {
		for(int j=i-1;j>=0;j--) 
			if(a[i]-a[j]==c)
				++answer;
	}
	cout<<answer<<endl;
	return 0;
}

二分做法

lower_bound 和 upper_bound 的用法:

  • lower_bound:第一个 ≥\geq≥ val的位置;

  • upper_bound:第一个 >\gt> val的位置。
    查询某个值出现的次数:

    auto lo = lower_bound(a.begin(), a.end(), target);
    auto hi = upper_bound(a.begin(), a.end(), target);
    int count = hi - lo; // target 出现的次数

100pts,O(Nlog⁡N)100pts,O(N \log N)100pts,O(NlogN):

cpp 复制代码
#include<bits/stdc++.h>
#define int long long
using namespace std;

bool cmp(int a,int b) {return a<b;}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	
	int n,c,answer=0;
	cin>>n>>c;
	vector<int> a(n);
	for(int i=0;i<n;i++)
		cin>>a[i];
	sort(a.begin(),a.end(),cmp);
	
	for(int i=n-1;i>=0;i--) {
		if(a[i]<c) break;
		int val=a[i]-c;
		auto l=lower_bound(a.begin(),a.end(),val);
		auto r=upper_bound(a.begin(),a.end(),val);
		answer+=(r-l);
	}
	cout<<answer<<endl;
	return 0;
}

双指针做法

100pts,O(Nlog⁡N)100pts,O(N \log N)100pts,O(NlogN):

思路与二分做法相同。

cpp 复制代码
#include<bits/stdc++.h>
#define int long long
using namespace std;

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    int n, c, answer = 0;
    cin >> n >> c;
    vector<int> a(n);
    for (int i = 0; i < n; i++)
        cin >> a[i];
    sort(a.begin(), a.end());
    
    int l = 0, r = 0;
    for (int i = 0; i < n; i++) {
        int target = a[i] - c;        while (l < n && a[l] < target) l++;
        while (r < n && a[r] <= target) r++;
        answer += r - l;
    }
    cout << answer << endl;
    return 0;
}
相关推荐
不会就选b5 小时前
算法日常・每日刷题--<动态规划>3
数据结构·算法
-dzk-6 小时前
【堆】LC 347.前 K 个高频元素
算法·堆
H.莓飛6 小时前
【数据结构】栈_OJ题
linux·数据结构·算法·centos
Zootopia6266 小时前
多架 eVTOL集群排班调度方案思考
人工智能·算法·数学建模·matlab·动态规划·无人机·evtol
可乐ea7 小时前
GitHub Security Lab 开源 Fuzzing Taskflow:让 LLM 智能体自己跑完 C/C++ 模糊测试
jvm·c++·github·模糊测试·mcp·代码agent·智能体自动化
和裕7 小时前
年度框架直供 vs 零散按需采购:定制纸箱采购成本、交付与服务核心区别全对比
大数据·运维·网络·人工智能·算法
朝朝辞暮i7 小时前
C++ 第 13 课:值传递 —— 为什么函数里改了,外面却没变?
java·c++·算法
淡海水7 小时前
02-02-原理篇-分代GC
算法·unity·c#·游戏引擎·.net·gc
无忧.芙桃8 小时前
C++语言原理与实践(十):vector类的底层实现
开发语言·c++·算法
无名猿8 小时前
std::variant 完全指南:类型安全的 union 与 std::visit 用法
c++·stl·标准库·现代c++