P1102数对

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

1.单纯的用减法会精度不够
2.其实答案已经展示出来了,也就是个搜索查找的问题

//使用map的一一映射关系
//map是一个key value,用数组插入的是时候,可以覆盖掉之前的关键字
#include<iostream>
#include<map>
using namespace std;
long  long int a[2000000];
map<long long int ,long long int>mp;
int main()
{
	int m;
	long long int n;
	long long int ans=0;
	cin>>m>>n;
	for(int i=1;i<=m;i++)
	{
		cin>>a[i];
		mp[a[i]]++;
		a[i]-=n;
	}
	for(int i=1;i<=m;i++)
	{
		ans+=mp[a[i]];
	}
	cout<<ans<<endl;
	return 0;
	
}

用一个二分的做法
如果这个数组是有序的,那么对于每一个A的值,在他后方就有一个B,满足两者差为c,用这两个函数,求出A与A+c这两个位置,找到一对

lower_bound(a,a+n,x)-a//下标从0开始,寻找大于等于x的值所在的下标
upper_bound(a,a+n,x)-a//下标从0开始,寻找大于x值坐在下标
for(int i=1;i<=N;i++)
{//求个数
ans+=((upper_bound(a+1,a+N+1,a[i]+C)-a)-(lower_bound(a+1,a+N+1,a[i]+C)-a));
#include<bits/stdc++.h>
using namespace std;
long long int a[200000];
int main()
{
	long long int m,n,ans=0;
	cin>>m>>n;
	for(int i=1;i<=m;i++)
	{
		cin>>a[i];
	}
	sort(a+1,a+m+1);
	for(int i=1;i<=m;i++)
	{
		ans+=((upper_bound(a+1,a+m+1,a[i]+n)-a)-(lower_bound(a+1,a+m+1,a[i]+n)-a));
	}
	cout<<ans;
	return 0;
}

双指针解决问题
可以先将原数组排序,然后每个对应a的b是连续的,找到两个端点,相减
维护两个右端点r1,r2
r1右移到a[r1]-a[1]<=c的最后位置的下一位,r2到满足a[r2]-a[1]<c最后一位`

#include <bits/stdc++.h>
#define ll long long

using namespace std;

const int N = 2e5 + 10;
int n , c;
int a[N];

int main () 
{
	cin >> n >> c;
	for(int i = 1 ; i <= n ; i ++) cin >> a[i];
	sort(a + 1 , a + 1 + n);
	int l = 1, r1 = 1 , r2 = 1;
	ll ans = 0;
	for(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[r2] - a[l] == c && a[r1 - 1] - a[l] == c && r1 - 1 >= 1) 	
			ans += r1 - r2;
	}
	cout << ans;
	return 0;
}

用哈希函数(真学不会)

#include<cstdio>
#define p 1000003
#define hash(a) a%p
using namespace std;
long long int n,m,a[p],ans;
struct node{
	long long x;
	int y;//x是这个位置的数,y是这个数出现了几次 
}h[p];
long long abs(long long x){return x<0?-x:x;
} 
int find(long long x)
{
	int y=hash(abs(x));
	while(h[y].x&&h[y].x!=x) y=hash(++y);
	return y;
}
void push(long long x){int y=find(x);h[y].y++;h[y].x=x;}//先找到此数在hash表中的位置,并将这个位置对应的数量+1,并且将数放进去
int check(long long x){return h[find(x)].y;}//输出这个数在hash表中出现的次数
int main()
{
	scanf("%lld%lld",&n,&m);
	for(long long i=1;i<=n;i++) scanf("%lld",&a[i]),push(a[i]);//输入并放入
	for(long long i=1;i<=n;i++) ans+=check(a[i]-m);//统计
	printf("%lld",ans);//输出
}
}

先摆上,以后看哈哈哈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值