接着上次的旅行。
此为查找第k小的数的一类题型,基本模式可同最小值最大化。
参考程序:
3579:
#include<cstdio>
#include<algorithm>
#define maxn 110000
using namespace std;
long long half;
int n;
int a[maxn];
bool Check(int mid){
long long sum=0;
for (int i=0;i<n;i++)
sum+=a+n-lower_bound(a+i+1,a+n,a[i]+mid);
return sum>half;
}
int main(){
while (scanf("%d",&n)==1){
for (int i=0;i<n;i++)
scanf("%d",&a[i]);
long long m=n*(n-1)/2;
half=m/2;
sort(a,a+n);
int l=0,r=a[n-1]-a[0]+1;
while (l+1<r){
int mid=(l+r)>>1;
if (Check(mid))l=mid;
else r=mid;
}
printf("%d\n",l);
}
return 0;
}
#include<cstdio>
#include<algorithm>
#define oo 100000
#define maxn 51000
using namespace std;
typedef long long LL;
LL n;
LL m;
LL num(LL i,LL j){
return i*i+oo*i+j*j-oo*j+i*j;
}
bool Check(LL k){
LL cnt=0;
for (int j=1;j<=n;j++){
int l=0,r=n+1;
while (l+1<r){
int i=(l+r)>>1;
if (num(i,j)<k)l=i;
else r=i;
}
cnt+=l;
}
return cnt<m;
}
int main(){
int T;
scanf("%d",&T);
while (T--){
scanf("%lld%lld",&n,&m);
LL l=-oo*n,r=3*n*n+oo*n;
while (l+1<r){
LL mid=(l+r)>>1;
if (Check(mid))l=mid;
else r=mid;
}
printf("%lld\n",l);
}
return 0;
}