题解:AT_abc364_d [ABC364D] K-th Nearest
思路
令 为 的值域(即 ),我们可以在 的时间复杂度内解决这个问题。
首先我们要对 和 排序,这是接下来二分的基础。
接下来我们二分我们要输出的答案。我们要在 区间内二分,显然这一步是 的。
一个细节是值域是 ,所以至少 ,但是如果 会 WA 掉极大数据。令 即可。
在我们二分完答案 之后,我们要考虑的就是如何快速求出一共有多少数在 序列中满足要求。
自然我们不能枚举。不难发现对于 ,满足条件的 都符合要求 。
我们可以在 序列中二分找出第一个大于等于 的数和第一个小于等于 的数,这样我们就找到了 序列符合条件的区间,即在这个区间内的数都符合条件。
接下来就可以求出区间长度,即当最远距离为 时,我们有多少点符合要求。如果符合条件的个数大于等于 个,就说明我们区间取大了,往小取。但是有可能这是符合要求点数大于等于 的最小距离,所以我们把答案记录下来。如果点数少于 个,即距离小了,我们就往大取。
时间复杂度 。
代码
#include<bits/stdc++.h>
using namespace std;
int n,a[200005],m;
struct node{
int id,x,k,ans;
}b[200005];
int cmp(node _,node __){
return _.x<__.x;
}
int cmp2(node _,node __){
return _.id<__.id;
}
int main(){
// freopen("data.txt","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=m;i++){
scanf("%d%d",&b[i].x,&b[i].k);
b[i].id=i;
}
n++;
a[n]=2147483647;
sort(a+1,a+n+1);
sort(b+1,b+m+1,cmp);
for(int i=1;i<=m;i++){
long long l=0,r=400000000,mid,ans=0;
// cout<<i<<endl;
while(l<r){
mid=(l+r)>>1;
int ll=lower_bound(a+1,a+n+1,b[i].x-mid)-a;
int rr=lower_bound(a+1,a+n+1,b[i].x+mid+1)-a;
rr--;
// cout<<mid<<' '<<ll<<' '<<rr<<endl;
int len=(rr-ll+1);
if(len>=b[i].k){
ans=mid;
r=mid;
}
else l=mid+1;
}
b[i].ans=ans;
// cout<<endl;
}
sort(b+1,b+m+1,cmp2);
for(int i=1;i<=m;i++){
printf("%d\n",b[i].ans);
}
return 0;
}

浙公网安备 33010602011771号