zoukankan      html  css  js  c++  java
  • [KD-tree] Luogu P2093 JZPFAR

    题目描述

    平面上有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
    ",Q.top().id);
    68     }
    69 }
  • 相关阅读:
    GridView中实现可收缩的面板
    android之xml数据解析(Pull)
    android之xml数据解析(DOM)
    android intent 传递list或者对象
    Android之单元测试
    Directx11教程(48) depth/stencil buffer的作用
    Directx11教程(47) alpha blend(4)雾的实现
    Directx11教程41 纹理映射(11)
    Directx11教程40 纹理映射(10)
    Directx11教程(46) alpha blend(3)
  • 原文地址:https://www.cnblogs.com/Comfortable/p/11317461.html
Copyright © 2011-2022 走看看