题意:给定一个序列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 */