zoukankan      html  css  js  c++  java
  • The Closest M Points BZOJ 3053

    The Closest M Points

    【问题描述】

    软工学院的课程很讨厌!ZLC同志遇到了一个头疼的问题:在K维空间里面有许多的点,对于某些给定的点,ZLC需要找到和它最近的m个点。

    (这里的距离指的是欧几里得距离:D(p, q) = D(q, p) =  sqrt((q1 - p1) ^ 2 + (q2 - p2) ^ 2 + (q3 - p3) ^ 2 + ... + (qn - pn) ^ 2)

    ZLC要去打Dota,所以就麻烦你帮忙解决一下了……

    【输入格式】

    第一行,两个非负整数:点数n(1 <= n <= 50000),和维度数k(1 <= k <= 5)。

    接下来的n行,每行k个整数,代表一个点的坐标。

    接下来一个正整数:给定的询问数量t(1 <= t <= 10000)

    下面2*t行:

      第一行,k个整数:给定点的坐标

      第二行:查询最近的m个点(1 <= m <= 10)

    所有坐标的绝对值不超过10000。

    有多组数据!

    【输出格式】

    对于每个询问,输出m+1行:

    第一行:"the closest m points are:" m为查询中的m

    接下来m行每行代表一个点,按照从近到远排序。

    保证方案唯一,下面这种情况不会出现:

    2 2

    1 1

    3 3

    1

    2 2

    1

    【样例输入】

    3 2

    1 1

    1 3

    3 4

    2

    2 3

    2

    2 3

    1

    【样例输出】

    5

    0

    4


    题解:

    题意就是求与给定点第一近到第m近的点

    用KD树查询

    期望答案的计算:与给定点最近且不与给定点在同一块的期望点必定在边界上

    开始时先将m个inf加入

    那么当查询到的点与给定点的距离小于堆顶与给定点的距离时,就去掉堆顶并加入这个点

    最后倒序输出

    注意初始化(虽然没写什么初始化,但是要考虑一下的)

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<cstdio>
      6 #include<cmath>
      7 #include<queue>
      8 using namespace std;
      9 inline void Scan(int &x)
     10 {
     11     int o = 1;
     12     char c;
     13     while((c = getchar()) < '0' || c > '9')
     14         if(c == '-') o = -1;
     15     x = c - '0';
     16     while((c = getchar()) >= '0' && c <= '9') x = x * 10 + c - '0';
     17     x *= o;
     18 }
     19 const int me = 50233;
     20 const int inf = 2147483647;
     21 struct dot
     22 {
     23     int lc, rc;
     24     int dis;
     25     int v[6], mi[6], ma[6];
     26 };
     27 dot point;
     28 dot c[me];
     29 dot tr[me];
     30 dot ans[me];
     31 struct name
     32 {
     33     int x;
     34     int dis;
     35 };
     36 inline bool operator < (const name &a, const name &b)
     37 {
     38     return a.dis < b.dis;
     39 }
     40 priority_queue <name> sta;
     41 int e, n, k, m;
     42 inline bool cmp(const dot &a, const dot &b)
     43 {
     44     return a.v[e] < b.v[e];
     45 }
     46 inline int Min(const int &x, const int &y)
     47 {
     48     return (x < y) ? x : y;
     49 }
     50 inline int Max(const int &x, const int &y)
     51 {
     52     return (x > y) ? x : y;
     53 }
     54 inline int Sqr(const int &x)
     55 {
     56     return x * x;
     57 }
     58 inline void Update(const int &x)
     59 {
     60     int l = tr[x].lc, r = tr[x].rc;
     61     for(int i = 0; i < k; ++i)
     62     {
     63         tr[x].mi[i] = tr[x].ma[i] = tr[x].v[i];
     64         if(l) tr[x].mi[i] = Min(tr[x].mi[i], tr[l].mi[i]), tr[x].ma[i] = Max(tr[x].ma[i], tr[l].ma[i]);
     65         if(r) tr[x].mi[i] = Min(tr[x].mi[i], tr[r].mi[i]), tr[x].ma[i] = Max(tr[x].ma[i], tr[r].ma[i]);
     66     }
     67 }
     68 int Build(const int &l, const int &r, int d)
     69 {
     70     if(d >= k) d -= k;
     71     e = d;
     72     int mi = l + r >> 1;
     73     nth_element(c + l, c + mi, c + r + 1, cmp);
     74     tr[mi] = c[mi];
     75     if(l < mi) tr[mi].lc = Build(l, mi - 1, d + 1);
     76     if(r > mi) tr[mi].rc = Build(mi + 1, r, d + 1);
     77     Update(mi);
     78     return mi;
     79 }
     80 inline int Dis(const int &x)
     81 {
     82     int sum = 0;
     83     for(int i = 0; i < k; ++i)
     84         sum += Sqr(tr[x].v[i] - point.v[i]);
     85     return sum;
     86 }
     87 inline int Get(const int &x)
     88 {
     89     int sum = 0;
     90     for(int i = 0; i < k; ++i)
     91     {
     92         if(point.v[i] < tr[x].mi[i]) sum += Sqr(tr[x].mi[i] - point.v[i]);
     93         if(point.v[i] > tr[x].ma[i]) sum += Sqr(point.v[i] - tr[x].ma[i]);
     94     }
     95     return sum;
     96 }
     97 void Ask(const int &x)
     98 {
     99     int dis = Dis(x);
    100     if(dis < sta.top().dis)
    101     {
    102         sta.pop();
    103         sta.push((name) {x, dis});
    104     }
    105     int le = inf, ri = inf;
    106     if(tr[x].lc) le = Get(tr[x].lc);
    107     if(tr[x].rc) ri = Get(tr[x].rc);
    108     if(le < ri)
    109     {
    110         if(le < sta.top().dis) Ask(tr[x].lc);
    111         if(ri < sta.top().dis) Ask(tr[x].rc);
    112     }
    113     else
    114     {
    115         if(ri < sta.top().dis) Ask(tr[x].rc);
    116         if(le < sta.top().dis) Ask(tr[x].lc);
    117     }
    118 }
    119 int main()
    120 {
    121 //    freopen("d.in", "r", stdin), freopen("d.out", "w", stdout);
    122     while(~scanf("%d", &n))
    123     {
    124         Scan(k);
    125         for(int i = 1; i <= n; ++i)
    126             for(int j = 0; j < k; ++j)
    127                 Scan(c[i].v[j]);
    128         int root = Build(1, n, 0);
    129         int t;
    130         Scan(t);
    131         while(t--)
    132         {
    133             for(int i = 0; i < k; ++i) Scan(point.v[i]);
    134             Scan(m);
    135             for(int i = 1; i <= m; ++i) sta.push((name) {0, inf});
    136             Ask(root);
    137             for(int i = 1; i <= m; ++i)
    138             {
    139                 ans[i] = tr[sta.top().x];
    140                 sta.pop();
    141             }
    142             printf("the closest %d points are:
    ", m);
    143             for(int i = m; i >= 1; --i)
    144             {
    145                 for(int j = 0; j < k - 1; ++j)
    146                     printf("%d ", ans[i].v[j]);
    147                 printf("%d
    ", ans[i].v[k - 1]);
    148             }
    149         }
    150     }
    151 }
  • 相关阅读:
    康师傅JVM:运行时数据区概述及线程(三)
    康师傅JVM:程序计数器(四)
    Git常用命令
    Arthas概述
    康师傅JVM:JVM与Java体系结构(一)
    LabVIEW 连接MySQL数据库
    LabVIEW dll 崩溃
    LabVIEW 关于定时的研究
    NI 配置管理软件MAX的一些功能使用介绍
    LabVIEW 串口通信
  • 原文地址:https://www.cnblogs.com/lytccc/p/6442180.html
Copyright © 2011-2022 走看看