P4357 [CQOI2016]K远点对 kd-tree

题意:

求二维平面内n个点的k远点对

题解:

  • 很明显是一个kdtree
  • 用小顶堆来维护最大的k个值即可 
  • 不断塞入最大值来更新
  • 可以增加一个剪枝  如果子树的最大距离比堆顶小  那就不用继续下去了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
struct point{ll x[2];}t[N],temp[N],a[N];
int mi[N][2],ma[N][2],lson[N],rson[N];
int st[N],top,ncnt,sort_dim,root;
bool operator<(point &a,point &b){return a.x[sort_dim]<b.x[sort_dim];};
void up(int x)
{
    for(int i=0;i<=1;i++)
    {
        mi[x][i]=ma[x][i]=t[x].x[i];
        if(lson[x])mi[x][i]=min(mi[x][i],mi[lson[x]][i]),ma[x][i]=max(ma[x][i],ma[lson[x]][i]);
        if(rson[x])mi[x][i]=min(mi[x][i],mi[rson[x]][i]),ma[x][i]=max(ma[x][i],ma[rson[x]][i]);
    }
}
void build(int l,int r,int &pos,int dim)
{
    if(l>r)return ;
    int mid=l+r>>1;pos=++ncnt;
    sort_dim=dim;
    nth_element(temp+l,temp+mid,temp+r+1);
    t[pos]=temp[mid];
    build(l,mid-1,lson[pos],dim^1);
    build(mid+1,r,rson[pos],dim^1);
    up(pos);
}
priority_queue<ll,vector<ll>,greater<ll> >q;
ll dis(point a,point b){return (a.x[0]-b.x[0])*(a.x[0]-b.x[0])+(a.x[1]-b.x[1])*(a.x[1]-b.x[1]);}
ll getdis(point a,int x)
{
    ll ans=0;
    ans=max(ans,dis(a,(point){mi[x][0],mi[x][1]}));
    ans=max(ans,dis(a,(point){mi[x][0],ma[x][1]}));
    ans=max(ans,dis(a,(point){ma[x][0],mi[x][1]}));
    ans=max(ans,dis(a,(point){ma[x][0],ma[x][1]}));
    return ans;
}
void qk(int x,point a)
{
    ll d=dis(a,t[x]);
    if(d>q.top())q.pop(),q.push(d);
    if(lson[x]){d=getdis(a,lson[x]);if(d>q.top())qk(lson[x],a);}
    if(rson[x]){d=getdis(a,rson[x]);if(d>q.top())qk(rson[x],a);}
}int k,n;
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++)scanf("%d%d",&temp[i].x[0],&temp[i].x[1]),a[i]=temp[i];
    build(1,n,root,0);
    for(int i=1;i<=2*k;i++)q.push(0);
    for(int i=1;i<=n;i++)qk(root,a[i]);
    cout<<q.top();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/bxd123/p/11773427.html