这道题因为要找A-B=C的个数;
我们可以(1)固定A找B
也可以(2)固定B找A;
两种方法,如果选择(1)
那就是找A-C我的建议是从后开始一步步缩减范围,因为写二分不得先排序吗?从后往前一步步减小,因为B=A-CB小于A所以右指针直接变小就行
不过我没变右指针,我是从头到尾都是从数组全部里面查找的
但是(2)方法中用了
先展示(1)
#include<iostream>
#include<algorithm>
using namespace std;
int a[200000];
int l = 1;
int n;
int SL(int l,int r,int x)
{
while (l < r)
{
int mid = l + r >> 1;
if (a[mid] >= x)r = mid;
else l = mid + 1;
}
if (a[l] == x)return l;
else return 0;
}
int SR(int l, int r, int x)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (a[mid] <= x)l = mid;
else r = mid - 1;
}
if (a[r] == x)return r;
else return 0;
}
int main()
{
int m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
long long res = 0,num;
sort(a + 1, a +1+n);
for (int i = 1; i <= n; i++)
{
if (a[i] == a[i - 1])res += num;
else
{
int x = a[i] - m;
int c = SL(l, n, x);
if (c)
{
int d = SR(l, n, x);
num = d - c + 1;
res += num;
}
else num = 0;
}
}
cout << res;
return 0;
}
可以看出在(1)中l和r在每次查找都是1和n
下面展示第二种
#include<iostream>
#include<algorithm>
using namespace std;
int a[200000];
int n;
int SL(int l,int r,int x)
{
while (l < r)
{
int mid = l + r >> 1;
if (a[mid] >= x)r = mid;
else l = mid + 1;
}
if (a[l] == x)return l;
else return 0;
}
int SR(int l, int r, int x)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (a[mid] <= x)l = mid;
else r = mid - 1;
}
if (a[r] == x)return r;
else return 0;
}
int main()
{
int m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
long long res = 0,num;
sort(a + 1, a +1+n);
for (int i = 1; i <= n; i++)
{
if(a[i]==a[i-1])res+=num;
else
{
int x=a[i]+m;
int c=SL(i+1,n,x);
if(c)
{
int d=SR(i+1,n,x);
num = d - c + 1;
res += num;
}
else num=0;
}
}
cout << res;
return 0;
}
在(2)中左指针会跟着i的变化而变化
其中if (a[i] == a[i - 1])res += num;这一句就是优化一下,如果后一位数和前一位数相同的话,直接加num就行