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);//输出
}
}
先摆上,以后看哈哈哈