CodeForces 1156C Match Points
You are given a set of points
x
1
,
x
2
,
.
.
.
,
x
n
x_1, x_2, ..., x_n
x1,x2,...,xn on the number line.
Two points
i
i
i and
j
j
j can be matched with each other if the following conditions hold:
neither i nor j is matched with any other point;
∣
x
i
−
x
j
∣
≥
z
|x_i−x_j|≥z
∣xi−xj∣≥z.What is the maximum number of pairs of points you can match with each other?
Input
The first line contains two integers
n
n
n and
z
(
2
≤
n
≤
2
⋅
1
0
5
,
1
≤
z
≤
1
0
9
)
z (2≤n≤2⋅10^5, 1≤z≤10^9)
z(2≤n≤2⋅105,1≤z≤109) — the number of points and the constraint on the distance between matched points, respectively.
The second line contains
n
n
n integers
x
1
,
x
2
,
.
.
.
,
x
n
(
1
≤
x
i
≤
1
0
9
)
x_1, x_2, ..., x_n (1≤x_i≤10^9)
x1,x2,...,xn(1≤xi≤109).
Output
Print one integer — the maximum number of pairs of points you can match with each other.
题意:
给出一个数组
a
a
a和一个数
z
z
z,问在
a
a
a中最多可以选择出多少对
i
i
i,
j
j
j,满足
∣
x
i
−
x
j
∣
≥
z
|x_i−x_j|≥z
∣xi−xj∣≥z,
i
i
i和
j
j
j不能重复选择。
思路:
假设
x
x
x是猜测的最多的对数,
s
s
s是真实的最多的对数,那么对于所有可行的
x
x
x,都有
x
<
=
s
x<=s
x<=s
且
f
(
x
)
=
(
x
<
=
s
?
1
:
0
)
f(x)=(x<=s?1:0)
f(x)=(x<=s?1:0)具有单调性,所以可以二分找答案。
先将数组
a
a
a排序,然后二分答案搜索最大的
x
x
x,
x
x
x表示最多可以选择出多少对
i
,
j
i,j
i,j。在check函数中,我们可以在排好序的
a
a
a里挑选出最小的
x
x
x个数,也就是前
x
x
x个,为它们匹配最大的
x
x
x个数字一一配对,可以证明这是最优的情况,也就是能够匹配出最多对的情况。然后我们一一检查,如果出现了
a
[
j
]
−
a
[
i
]
<
z
a[j]-a[i]<z
a[j]−a[i]<z,那么这个
a
[
i
]
a[i]
a[i]就需要更大的
a
[
j
]
a[j]
a[j],但如果给这个
a
[
i
]
a[i]
a[i]匹配更大的
a
[
j
]
a[j]
a[j],当前的
a
[
j
]
a[j]
a[j]就会被浪费了,从而凑不出完整的
x
x
x对,所以此时return 0 , 这个
x
x
x不成立。
代码:
#include<iostream>
#include<algorithm>
using namespace std ;
#define ll long long
const ll N = 2e5+9 ;
void updata( ll &a , ll b ){if(b>a)a=b;}
ll n , z ;
ll a[ N ] ;
bool check( ll x ){
if( x > n/2 ) return 0 ;
for( int i = 1 ; i <= x ; i ++ ){
ll p1 = i , p2 = n-x+i ;//第i个和倒数第i个作比较
if( a[ p2 ] - a[ p1 ] < z ) return 0 ;
}
return 1 ;
}
int main(){
cin >> n >> z ;
for( int i = 1 ; i <= n ; i ++ ) cin >> a[ i ] ;
sort( a+1 , a+1+n ) ;
ll l , r , mid , ans = -1 , f ;
l = 0 , r = n+9 ;
while( l <= r ){
mid = l+r >> 1 ;
f = check( mid ) ;
//cout << "mid=" << mid << " f=" << f << "\n" ;
if( f ){ l = mid + 1 ; updata( ans , mid ) ; }
else r = mid - 1 ;
}
cout << ans << "\n" ;
return 0 ;
}