链接:A-B数对
题目描述出题是一件痛苦的事情!
相同的题目看多了也会有审美疲劳,于是我舍弃了大家所熟悉的 A+B Problem,改用 A-B 了哈哈!
好吧,题目是这样的:给出一串数以及一个数字 C,要求计算出所有 A - B = C的数对的个数(不同位置的数字一样的数对算不同的数对)。
输入格式输入共两行。
第一行,两个整数 N, C。
第二行,N个整数,作为要求处理的那串数。
输出格式一行,表示该串数中包含的满足 A - B = C的数对的个数。
输入输出样例输入
4 1
1 1 2 3
输出
3
说明/提示
对于 75% 的数据,1≤N≤2000。
对于100% 的数据,1≤N≤2×105;
保证所有输入数据绝对值小于 230,且 C≥1。
2017/4/29 新添数据两组
思路11,这题是在该数列中,找A,B。使得A-B之差为C;
2,我们由A-B=C,可以变成A=B+C,这样我们可以把一个元素看成B,然后在剩下元素中找B+C即A,然后统计和为B+C的个数;
3,然后把每个元素逐个看成B,找和为B+C的个数;
4,找和为B+C的个数,就是本题要二分完成的,我们可以利用二分找和为B+C的首位置,再找和为B+C的末位置,就可以了;
#include思路2using namespace std; //A-B=C ==> A=B+C,把每个元素看成B,然后在数组中找B+C的起始位置与终止位置; const int N=2e5+100; int q[N]; long long n,m,cnt;//这里会爆int(试了) int main() { scanf("%lld%lld",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&q[i]); sort(q+1,q+n+1);//这里要先排序,因为题目没有说是有序的,但是样例却是有序的,就很坑 for(int i=1;i<=n;i++) { int b=q[i]; //下面求首次出现B+C 的位置 int l=1,r=n; while(l int mid=(l+r)/2; if(q[mid]>=(b+m)) r=mid; else l=mid+1; } int left=l; //下面求末次出现B+C 的位置 l=1; r=n; while(l int mid=(l+r+1)/2; if(q[mid]<=(b+m)) l=mid; else r=mid-1; } int right=l; if(q[l]==(b+m))//如果没有找到这个数,意思就是不存在这个数那么就不要 cnt +=(right-left+1);//两次求得 位置之差 } printf("%lldn",cnt); return 0; }
1,还有一种直接的,就是把每个元素看成B,然后再剩下找使得A-B差为C;
2,这里就不需要二分找了,但是时间复杂度应该不一样;
#include#include using namespace std; const int N=2e5+100; int arr[N]; int main() { int n,c; scanf("%d%d",&n,&c); for(int i=0;i scanf("%d",&arr[i]); } sort(arr,arr+n);//排序 int count=0; for(int i=0;i for(int j=i+1;j if(arr[j]-arr[i]==c) { count++;//找差为C的个数 } if(arr[j]-arr[i]>c) { break; } } } printf("%dn",count); return 0; }
总结:
1,善于转化,把题目转化成自己可以理解,容易解决的样子;
2,要注意二分的边界,是否等于,以及等于之后的赋值;
3,勤加练习,后面总结关于二分的介绍,模板等等;



