topic
TT is a serious cat lover who indulges in the cat channel on station B every day.
One day, TT's friend ZJM decided to give TT a problem. If TT can solve this problem, ZJM will buy a cute cat and give it to TT.
The task content is, given an N number array cat [i], and use this array to generate a new array ans [i]. The new array is defined as for any i, j and i! = J, all have ans [] = abs (cat [i]-cat [j]), 1 <= i <j <= N. Try to find the median of this new array. The median is the number corresponding to the (len + 1) / 2 position after sorting, and '/' is rounded down.
Input
Multiple sets of input, each time enter an N, indicating that there are N numbers, and then enter a sequence cat of length N, cat [i] <= 1e9, 3 <= n <= 1e5.
Output
Output the median of the new array ans.
Sample Input
4
1 3 2 4
3
1 10 2
Sample Output
1
8
Ideas
The meaning of the problem is that, given an array cat [], choose two of the numbers to make a difference, and find the absolute value, the absolute value of all the differences form a new array ans [], find the median of ans [] . Because | ab | = | ba |, the problem can be converted to sort cat [] in ascending order, any j> i, find cat [j] -cat [i], form ans [], and find the median.
The brute force method is to calculate the array ans [] and find the median, the complexity is O (n ^ 2), which is unacceptable.
Since the number n of the elements in the cat [] array is known, the number of elements in the ans [] array is n * (n-1) / 2, that is, the subscript pos = ( (n-1) * n / 2 + 1) / 2. In this way, the solution process can be achieved with two dichotomies.
In the first dichotomy, find the median. Let the left boundary l be 1, and the right boundary r be the largest value in ans, namely cat [n-1] -cat [0]. When l <r, loop, mid = (l + r) / 2, if the rank of mid is less than or equal to the median of ans [], then l = mid + 1, rslt = mid; otherwise r = mid-1. In the cycle, ans does not necessarily exist in ans [], but by continuously moving the left and right boundaries to approximate, at the end of the loop, rslt must be fixed as a number present in ans []. For example, a sequence in ans [] is a, b, c, where b is the median, then for numbers belonging to (0, a), its ranking is less than pos; for numbers belonging to (a, b), Its ranking is equal to pos; for numbers belonging to (a, + inf), its ranking is greater than pos. So update rslt when <=. The
second dichotomy process finds the ranking. Obviously, in the above process, because it cannot be directly obtained ans [], you need to design a function to find the rank of x in ans [], that is, calculate the logarithm of the binary tuple of cat [j] -cat [i] <x, and shift the term to get cat [j] <cat [i ] + x. Enumerate subscript i, and calculate the number of subscript j that meet the conditions.
Code
#include <cstdio>
#include <algorithm>
using namespace std;
int n;
int cat[100005];
int Rank(int x){//查找x在ans[]的名次
int rank=0;
for(int i=0;i<n;i++){
int l=i+1,r=n-1,ans=n;
while(l<=r){
int j=(l+r)/2;
if(cat[j]<cat[i]+x){
l=j+1;
}
else{
r=j-1;
ans=j;
}
}
rank+=(ans-i-1);//去除cat[j]-cat[i]<=0的部分
}
return rank+1;
}
int find(){
int l=1,r=cat[n-1]-cat[0],pos=((n-1)*n/2+1)/2,ans=0;
while(l<=r){
int mid=(l+r)/2;
if(Rank(mid)<=pos){
l=mid+1;
ans=mid;
}
else{
r=mid-1;
}
}
return ans;
}
int main() {
while(scanf("%d",&n)!=EOF){
for(int i=0;i<n;i++){
scanf("%d",&cat[i]);
}
sort(cat,cat+n);
int ans=find();
printf("%d\n",ans);
}
return 0;
}