中位数 题解
题意:给定一个序列a,求出这个序列的所有无序数对(一共有n*(n-1)/2个)的差的绝对值的中位数
显然,n^2枚举是会TLE掉的,那么我们换一种思路:二分答案;
对于每个答案,我们可以O(nlogn)验证,比较好想;
然后如果常熟大的话还是会TLE,怎么办呢?
那就是把验证复杂度降为O(n)
其实仔细想一想会发现,验证里的二分出的位置具有单调性,所以双指针扫一遍就可以了;
这种题主要在于细节处理;
#include <bits/stdc++.h>
#pragma GCC optimize(2)
#define inc(i,a,b) for(register int i=a;i<=b;i++)
using namespace std;
const int MXR=2e5+2;
long long val[MXR];
int n;
long long check(long long mid)
{
long long res=0;
int j=1;
inc(i,1,n){
while(val[i]-val[j]>=mid) ++j;
res+=(j-1);
}
return res;
}
signed main()
{
cin>>n;
inc(i,1,n) cin>>val[i];
sort(val+1,val+1+n);
long long L=0,R=1e17+1;
long long goal=n*(n-1)/4;
while(L<R){
long long mid=(L+R)/2;
long long gg=check(mid);
if(gg>goal){
L=mid+1;
}
else{
R=mid;
}
}
if((n*(n-1)/2)&1){
cout<<L-1<<endl;
//cout<<"this is a test";
return 0;
}
else{
long long tmp=L-1;
L=0;R=1e17+1;
while(L<R){
long long mid=(L+R)/2;
long long gg=check(mid);
//cout<<mid<<"-"<<gg<<endl;
if(gg>=goal){
L=mid+1;
}
else{
R=mid;
}
}
//cout<<tmp<<endl;
cout<<(L-1+tmp)/2<<endl;
}
}
/*
4
1 4 3 4
3
100 200 400
5
200 400 600 800 1000
*/
众人皆醉我独醒,举世皆浊我独清

浙公网安备 33010602011771号