【题目分析】

典型的KD-Tree例题,求k维空间中的最近点对,只需要在判断的过程中加上一个优先队列,就可以了。

【代码】

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>

#include <set>
#include <map>
#include <string>
#include <algorithm>
#include <vector>
#include <iostream>
#include <queue>

using namespace std;

#define maxn 1000005
#define inf (0x3f3f3f3f)
#define mk(a,b) make_pair(a,b)

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;
}

int D,rt,n,base,m,x;

struct node{
    int d[6],mx[6],mn[6],l,r;
    int operator [] (int x) {return d[x];}
    void init() {for (int i=0;i<base;++i) d[i]=read();}
}t[maxn],now;

bool operator < (node a,node b) {return a[D]<b[D];}

void update(int k)
{
    for (int i=0;i<base;++i)
    {
        t[k].mn[i]=min(t[k][i],min(t[t[k].l].mn[i],t[t[k].r].mn[i]));
        t[k].mx[i]=max(t[k][i],max(t[t[k].l].mx[i],t[t[k].r].mx[i]));
    }
}

int build(int l,int r,int dir)
{
    D=dir;
    int mid=(l+r)/2;
    nth_element(t+l,t+mid,t+r+1);
    for (int i=0;i<base;++i) t[mid].mn[i]=t[mid].mx[i]=t[mid][i];
    if (l<mid) t[mid].l=build(l,mid-1,(dir+1)%base); else t[mid].l=0;
    if (r>mid) t[mid].r=build(mid+1,r,(dir+1)%base); else t[mid].r=0;
    update(mid);
    return mid;
}

int dis(node a,node b)
{
    int ret=0;
    for (int i=0;i<base;++i)
        ret+=(a[i]-b[i])*(a[i]-b[i]);
    return ret;
}

pair <int,int> pa;
int ans[maxn];
priority_queue <pair<int,int> > q;

int getdis(int k)
{
    if (!k) return inf;
    int ret=0;
    for (int i=0;i<base;++i)
        if (now[i]<t[k].mn[i]) ret+=(t[k].mn[i]-now[i])*(t[k].mn[i]-now[i]);
    for (int i=0;i<base;++i)
        if (now[i]>t[k].mx[i]) ret+=(now[i]-t[k].mx[i])*(now[i]-t[k].mx[i]);
    return ret;
}

void query(int k)
{
    if (!k) return ;
    int dl=getdis(t[k].l),dr=getdis(t[k].r),d0=dis(t[k],now);
    if (d0<q.top().first) {q.pop(); q.push(mk(d0,k));}
    if (dl<dr)
    {
        if (dl<q.top().first) query(t[k].l);
        if (dr<q.top().first) query(t[k].r);
    }
    else
    {
        if (dr<q.top().first) query(t[k].r);
        if (dl<q.top().first) query(t[k].l);
    }
}

int main()
{
    while (scanf("%d%d",&n,&base)!=EOF)
    {
//      memset(t,0,sizeof t);
//      n=read(); base=read();
        for (int i=0;i<base;++i) t[0].mn[i]=inf,t[0].mx[i]=-inf;
        for (int i=1;i<=n;++i) t[i].init();
        rt=build(1,n,0);
        m=read();
        while (m--)
        {
            now.init(); x=read();
            for (int i=0;i<x;++i) q.push(mk(inf,0));
            query(rt);
            printf("the closest %d points are:\n",x);
            for (int i=x;i>=1;--i) ans[i]=q.top().second,q.pop();
            for (int i=1;i<=x;++i)
                for (int j=0;j<base;++j)
                    printf("%d%c",t[ans[i]][j],j==base-1?'\n':' ');
        }
    }
}

  

BZOJ 3053 The Closest M Points的更多相关文章

  1. BZOJ 3053: The Closest M Points(K-D Tree)

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1235  Solved: 418[Submit][Status][Discuss] Descripti ...

  2. bzoj 3053: The Closest M Points【KD-tree】

    多维KDtree板子 左右儿子的估价用mn~mx当区间,假设区间里的数都存在:k维轮着做割点 #include<iostream> #include<cstdio> #incl ...

  3. 【BZOJ】3053: The Closest M Points(kdtree)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3053 本来是1a的QAQ.... 没看到有多组数据啊.....斯巴达!!!!!!!!!!!!!!!! ...

  4. 【BZOJ】【3053】The Closest M Points

    KD-Tree 题目大意:K维空间内,与给定点欧几里得距离最近的 m 个点. KD树啊……还能怎样啊……然而扩展到k维其实并没多么复杂?除了我已经脑补不出建树过程……不过代码好像变化不大>_&g ...

  5. bzoj 3053 HDU 4347 : The Closest M Points kd树

    bzoj 3053 HDU 4347 : The Closest M Points  kd树 题目大意:求k维空间内某点的前k近的点. 就是一般的kd树,根据实测发现,kd树的两种建树方式,即按照方差 ...

  6. 【BZOJ 3053】The Closest M Points

    KDTree模板,在m维空间中找最近的k个点,用的是欧几里德距离. 理解了好久,昨晚始终不明白那些“估价函数”,后来才知道分情况讨论,≤k还是=k,在当前这一维度距离过线还是不过线,过线则要继续搜索另 ...

  7. The Closest M Points BZOJ 3053

    The Closest M Points [问题描述] 软工学院的课程很讨厌!ZLC同志遇到了一个头疼的问题:在K维空间里面有许多的点,对于某些给定的点,ZLC需要找到和它最近的m个点. (这里的距离 ...

  8. 【kd-tree】bzoj3053 The Closest M Points

    同p2626.由于K比较小,所以不必用堆. #include<cstdio> #include<cstring> #include<cmath> #include& ...

  9. 【HDOJ】4347 The Closest M Points

    居然是KD解. /* 4347 */ #include <iostream> #include <sstream> #include <string> #inclu ...

随机推荐

  1. 【linux】虚拟机安装centos后ping ip地址出现错误:Network is unreachable

    来源:https://my.oschina.net/stonezing/blog/515480 方案一: 进入/etc/sysconfig/network-scripts/ 查看这下面的文件 每个人的 ...

  2. sqlserver 导出数据字典

    -- 数据字典 SELECT ( then d.name else '' end)表名, a.colorder 字段序号, a.name 字段名, ( then '√'else '' end) 标识, ...

  3. openfile学习笔记

    Openfiler是在rPath Linux基础上开发的,它能够作为一个独立的Linux操作系统发行.Openfiler是一款非常好的存储管理操作系统,开源免费,通过web界面对 存储磁盘的管理,支持 ...

  4. DB2应用中嵌入式SQL取值入本地变量

    Declare section for host variables in C and C++ embedded SQL applications You must use an SQL declar ...

  5. 16.迭代器模式(Iterator Pattern)

    using System; namespace ConsoleApplication9 { class Program { /// <summary> /// 迭代器模式提供了一种方法顺序 ...

  6. Java并发编程实现概览

    并发概览 >>同步 如何同步多个线程对共享资源的访问是多线程编程中最基本的问题之一.当多个线程并发访问共享数据时会出现数据处于计算中间状态或者不一致的问题,从而影响到程序的正确运行.我们通 ...

  7. WPF Navigation

    在开始学习WPF时,一开始对WPF的Window, Page, UserControl感到很迷惑.不知道什么时候该使用哪一个.下面简单介绍一下这三者的区别. Window:故名思意,桌面程序的窗体.在 ...

  8. 跟着鸟哥学Linux系列笔记2-第10章VIM学习

    跟着鸟哥学Linux系列笔记0-扫盲之概念 跟着鸟哥学Linux系列笔记0-如何解决问题 跟着鸟哥学Linux系列笔记1 常用的文本编辑器:Emacs, pico, nano, joe, vim VI ...

  9. cocos2d-x CCScrollView和CCTableView的使用(转载)

    转载请注明来自:Alex Zhou的程序世界,本文链接:http://codingnow.cn/cocos2d-x/1024.html //============================== ...

  10. Json转换利器Gson之实例一-简单对象转化和带泛型的List转化 (转)

    Gson 是 Google 提供的用来在 Java 对象和 JSON 数据之间进行映射的 Java 类库.可以将一个 JSON 字符串转成一个 Java 对象,或者反过来. jar和源码下载地址: h ...