[CQOI2016]K远点对(KD-Tree)
Posted hfctf0210
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CQOI2016]K远点对(KD-Tree)相关的知识,希望对你有一定的参考价值。
暴力的做法应该是这样的,维护大小为k的堆,每次插入两点间距离并弹出堆顶。
然后这个做法显然是可以KD-Tree优化的,建立KD-Tree,然后如果该平面内最远点小于堆顶,则直接退出。就当做是复习很久没做的KD-Tree了。
不过有一个细节要注意,求最远点对,(1,2)->(2,1)算一对,所以堆的大小应该是2*k
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+7; struct pointll d[2];a[N]; struct nodeint mn[2],mx[2],lc,rc;point a;t[N]; priority_queue<ll,vector<ll>,greater<ll> >q; int n,m,rt,D; bool operator<(point a,point b)return a.d[D]<b.d[D]; void pushup(int x,int y) t[x].mn[0]=min(t[x].mn[0],t[y].mn[0]); t[x].mn[1]=min(t[x].mn[1],t[y].mn[1]); t[x].mx[0]=max(t[x].mx[0],t[y].mx[0]); t[x].mx[1]=max(t[x].mx[1],t[y].mx[1]); void build(int&k,int l,int r,int d) k=0; if(l>r)return; D=d; int mid=l+r>>1; nth_element(a+l,a+mid,a+r+1); k=mid; t[k].mn[0]=t[k].mx[0]=t[k].a.d[0]=a[k].d[0]; t[k].mn[1]=t[k].mx[1]=t[k].a.d[1]=a[k].d[1]; build(t[k].lc,l,mid-1,d^1); if(t[k].lc)pushup(k,t[k].lc); build(t[k].rc,mid+1,r,d^1); if(t[k].rc)pushup(k,t[k].rc); ll getdis(point a,point b) return(a.d[0]-b.d[0])*(a.d[0]-b.d[0])+(a.d[1]-b.d[1])*(a.d[1]-b.d[1]); ll getdis2(point a,node b) ll ret=0; ret=max(ret,getdis(a,(point)b.mn[0],b.mn[1])); ret=max(ret,getdis(a,(point)b.mn[0],b.mx[1])); ret=max(ret,getdis(a,(point)b.mx[0],b.mn[1])); ret=max(ret,getdis(a,(point)b.mx[0],b.mx[1])); return ret; void query(int k,point a) ll dis=getdis(a,t[k].a); if(dis>q.top())q.pop(),q.push(dis); if(t[k].lc) dis=getdis2(a,t[t[k].lc]); if(dis>q.top())query(t[k].lc,a); if(t[k].rc) dis=getdis2(a,t[t[k].rc]); if(dis>q.top())query(t[k].rc,a); int main() scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%lld%lld",&a[i].d[0],&a[i].d[1]); build(rt,1,n,0); for(int i=1;i<=m*2;i++)q.push(0); for(int i=1;i<=n;i++)query(rt,a[i]); printf("%lld",q.top());
以上是关于[CQOI2016]K远点对(KD-Tree)的主要内容,如果未能解决你的问题,请参考以下文章