BZOJ 4520 [Cqoi2016]K远点对(KD树)
【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=4520
【题目大意】
求K远点对距离
【题解】
修改估价函数为欧式上界估价,对每个点进行dfs,
因为是无向点对,在小根堆中保留前2k个距离,
不断更新堆顶元素即可。
【代码】
#include <cstdio> #include <algorithm> #include <queue> using namespace std; typedef long long LL; const int N=200000; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } struct data{ LL dis; data(){}; data(const LL&x){dis=x;} bool operator <(const data&x)const{return dis>x.dis;} }tmp; priority_queue<data>q; namespace KD_Tree{ struct Dot{ int d[2],mn[2],mx[2],l,r; Dot(){l=r=0;} Dot(int x,int y){d[0]=x;d[1]=y;l=r=0;} int& operator [] (int x){return d[x];} }; int D,dcnt=0,pt[N]; Dot T[N],p[N]; bool operator<(Dot a,Dot b){return a[D]<b[D];} inline void umax(int&a,int b){if(a<b)a=b;} inline void umin(int&a,int b){if(a>b)a=b;} inline bool cmp(int x,int y){return T[x][D]<T[y][D];} inline void up(int x){ T[x].mn[0]=T[x].mx[0]=T[x][0]; T[x].mn[1]=T[x].mx[1]=T[x][1]; if(T[x].l){ umax(T[x].mx[0],T[T[x].l].mx[0]); umin(T[x].mn[0],T[T[x].l].mn[0]); umax(T[x].mx[1],T[T[x].l].mx[1]); umin(T[x].mn[1],T[T[x].l].mn[1]); } if(T[x].r){ umax(T[x].mx[0],T[T[x].r].mx[0]); umin(T[x].mn[0],T[T[x].r].mn[0]); umax(T[x].mx[1],T[T[x].r].mx[1]); umin(T[x].mn[1],T[T[x].r].mn[1]); } } void AddDot(int x,int y){ ++dcnt; pt[dcnt]=dcnt; p[dcnt][0]=x; p[dcnt][1]=y; } int build(int l,int r,int now){ if(l>r)return 0; int mid=(l+r)>>1; D=now; nth_element(p+l,p+mid,p+r+1); T[mid]=p[mid]; for(int i=0;i<2;i++)T[mid].mn[i]=T[mid].mx[i]=T[mid][i]; if(l<mid)T[mid].l=build(l,mid-1,now^1); if(r>mid)T[mid].r=build(mid+1,r,now^1); return up(mid),mid; } LL sqr(LL x){return x*x;} inline LL dist(int x,int px,int py){ LL dis=0; if(!x)return 0; dis+=max(sqr(T[x].mn[0]-px),sqr(T[x].mx[0]-px)); dis+=max(sqr(T[x].mn[1]-py),sqr(T[x].mx[1]-py)); return dis; } } void query(int x,int px,int py){ if(!x)return; LL dl,dr,d0=sqr(T[x][0]-px)+sqr(T[x][1]-py); dl=T[x].l?dist(T[x].l,px,py):0; dr=T[x].r?dist(T[x].r,px,py):0; if(d0>q.top().dis)q.pop(),q.push(data(d0)); if(dl>dr){ if(dl>q.top().dis)query(T[x].l,px,py); if(dr>q.top().dis)query(T[x].r,px,py); } else{ if(dr>q.top().dis)query(T[x].r,px,py); if(dl>q.top().dis)query(T[x].l,px,py); } } } int n,k; int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++)KD_Tree::AddDot(read(),read()); int root=KD_Tree::build(1,n,0); for(int i=0;i<k+k;i++)q.push(tmp); for(int i=1;i<=n;i++)KD_Tree::query(root,KD_Tree::p[i][0],KD_Tree::p[i][1]); printf("%lld\n",q.top().dis); return 0; }
愿你出走半生,归来仍是少年