C. Number of Pairs 【Codeforces Round #725 (Div. 3)】

题意

题目链接
给你一个有 n n n个整数的数组 a a a,当 1 ≤ i ≤ j ≤ n 1≤i≤j≤n 1ijn时,求所有满足 l ≤ a i + a j ≤ r l≤a_{i}+a_{j}≤r lai+ajr ( i , j ) (i,j) (i,j)的对数。所有测试样例中 n n n的总和满足 ∑ n ≤ 2 e 5 \sum{n}≤2e5 n2e5

思路

1.先对数组中的数从小到大排序。
2.对于从小到大的第 i i i个数,对第 i + 1 i+1 i+1 n n n个数二分,分别找出最小的满足条件的边界和最大的满足条件的边界。
3.最大边界与最小边界位置的差,再加1,就是当前的对数。
4.遍历计算所有对数的总和,就是答案。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 2e5+5;
ll a[maxn];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	ll t;cin>>t;
	while(t--){
		ll n,l,r;
		cin>>n>>l>>r;
		for(ll i=1;i<=n;i++)cin>>a[i];
		sort(a+1,a+1+n);
		ll ans = 0;
		for(ll i=1;i<n;i++){
			ll left = i+1, right = n, pos_l = -1, pos_r = -1;
			while(left<=right){
				ll mid = (left+right)>>1;
				if(a[mid]+a[i]<l)left = mid+1;
				else if(a[mid]+a[i]>=l)right = mid-1, pos_l=mid;
			}
			left = i+1, right = n;
			while(left<=right){
				ll mid = (left+right)>>1;
				if(a[mid]+a[i]<=r)left = mid+1,pos_r=mid;
				else if(a[mid]+a[i]>r)right = mid-1;
			}
			if(pos_l!=-1&&pos_r!=-1){
				if(pos_l<=pos_r){
					ans+=(pos_r-pos_l+1);
				}
			}
		}
		cout<<ans<<endl;
	}
    return 0;
}

总结

在二分时,需要注意只有满足条件才记录当前位置,而且只要当前满足条件,就要继续寻找,而不能停止寻找。直到继续寻找之后无法满足条件,再终止循环。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

keguaiguai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值