P1102 A-B数对

这道题因为要找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就行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值