题目描述
平面上有n个点。现在有m次询问,每次给定一个点(px, py)和一个整数k,输出n个点中离(px, py)的距离第k大的点的标号。如果有两个(或多个)点距离(px, py)相同,那么认为标号较小的点距离较大。
题解
- 利用KD-Tree算法,求二维平面内到一定点的第k远点
- 正常建树,由于题目要求输出第k远点的编号,我们需记录一下每个节点的id,用优先队列动态维护小根堆,保持k个最优点,最后输出堆顶元素的编号即可
代码
1 #include <queue> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #define sqr(x) (x)*(x) 7 #define N 100010 8 #define ll long long 9 using namespace std; 10 ll n,m,X,Y,tot,D,root; 11 struct node 12 { 13 ll dis,id; 14 bool operator < (const node &a)const { return dis>a.dis||(dis==a.dis&&id<a.id); } 15 }; 16 struct Node 17 { 18 ll x[2],id; 19 bool operator < (const Node &a) const {return x[D]<a.x[D];} 20 }p[N]; 21 struct kdtree { Node p; ll mx[2],mn[2],ls,rs,id; }t[N]; 22 priority_queue<node>Q; 23 ll dis(kdtree t) { return sqr(t.p.x[0]-X)+sqr(t.p.x[1]-Y); } 24 ll mxdis(kdtree t) { return max(sqr((t.mn[0]-X)),sqr(t.mx[0]-X))+max(sqr(t.mn[1]-Y),sqr(t.mx[1]-Y)); } 25 void update(ll d) 26 { 27 if (!d) return; 28 ll l=t[d].ls,r=t[d].rs; 29 if (l) t[d].mn[0]=min(t[d].mn[0],t[l].mn[0]),t[d].mx[0]=max(t[d].mx[0],t[l].mx[0]),t[d].mn[1]=min(t[d].mn[1],t[l].mn[1]),t[d].mx[1]=max(t[d].mx[1],t[l].mx[1]); 30 if (r) t[d].mn[0]=min(t[d].mn[0],t[r].mn[0]),t[d].mx[0]=max(t[d].mx[0],t[r].mx[0]),t[d].mn[1]=min(t[d].mn[1],t[r].mn[1]),t[d].mx[1]=max(t[d].mx[1],t[r].mx[1]); 31 } 32 void build(ll &d,ll l,ll r,ll x) 33 { 34 if (l>r) return; 35 ll mid=l+r>>1; 36 D=x,d=++tot,nth_element(p+l,p+mid,p+r+1); 37 t[d].p=p[mid],t[d].id=t[d].p.id,t[d].mn[0]=t[d].mx[0]=t[d].p.x[0],t[d].mn[1]=t[d].mx[1]=t[d].p.x[1]; 38 build(t[d].ls,l,mid-1,x^1),build(t[d].rs,mid+1,r,x^1),update(d); 39 } 40 void query(ll d) 41 { 42 if (!d) return; 43 ll p=dis(t[d]),l=t[d].ls,r=t[d].rs,L,R; 44 if (p>Q.top().dis||(p==Q.top().dis&&t[d].id<Q.top().id)) Q.pop(),Q.push((node){p,t[d].id}); 45 if (l) L=mxdis(t[l]); if (r) R=mxdis(t[r]); 46 if (L>R) 47 { 48 if (L>=Q.top().dis) query(l); 49 if (R>=Q.top().dis) query(r); 50 } 51 else 52 { 53 if (R>=Q.top().dis) query(r); 54 if (L>=Q.top().dis) query(l); 55 } 56 } 57 int main() 58 { 59 scanf("%lld",&n); 60 for (ll i=1;i<=n;i++) scanf("%lld%lld",&p[i].x[0],&p[i].x[1]),p[i].id=i; 61 build(root,1,n,0),scanf("%lld",&m); 62 for (ll i=1,k;i<=m;i++) 63 { 64 scanf("%lld%lld%lld",&X,&Y,&k); 65 while (Q.size()) Q.pop(); 66 for (ll j=1;j<=k;j++) Q.push((node){-1,0}); 67 query(root),printf("%lld\n",Q.top().id); 68 } 69 }