bzoj 3053 HDU 4347 : The Closest M Points kd树

bzoj 3053 HDU 4347 : The Closest M Points  kd树

题目大意:求k维空间内某点的前k近的点。

就是一般的kd树,根据实测发现,kd树的两种建树方式,即按照方差较大的维度分开(建树常数大)或者每一位轮换分割(询问常数大),后者更快也更好些,以后就果断写第二种了。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 510000
#define MAXT MAXN
#define MAXM 6
#define sqr(x) ((qword)(x)*(x))
#define INF 0x3f3f3f3f
typedef long long qword;
int n,m;
struct point
{
        int a[MAXM];
        qword dis;
        void pm()
        {
                printf("(%d",a[0]);
                for (int i=1;i<m;i++)
                        printf(",%d",a[i]);
                printf(")");
        }
        void pm2()
        {
                for (int i=0;i<m-1;i++)
                        printf("%d ",a[i]);
                printf("%d\n",a[m-1]);
        }
}pl[MAXN];
bool cmp_0(const point &p1,const point &p2){
        return p1.a[0]<p2.a[0];
}
bool cmp_1(const point &p1,const point &p2){
        return p1.a[1]<p2.a[1];
}
bool cmp_2(const point &p1,const point &p2){
        return p1.a[2]<p2.a[2];
}
bool cmp_3(const point &p1,const point &p2){
        return p1.a[3]<p2.a[3];
}
bool cmp_4(const point &p1,const point &p2){
        return p1.a[4]<p2.a[4];
}
bool cmp_d(const point &p1,const point &p2){
        return p1.dis<p2.dis;
}
struct kdt_node
{
        int a[MAXM];
        int dd,mxp[MAXM],mnp[MAXM];
        int ch[2];
        int ptr;
}kdt[MAXT];
qword get_dis(point &pt,kdt_node &pn)
{
        qword ret=0;
        for (int j=0;j<m;j++)
                if (pt.a[j]<pn.mnp[j] || pt.a[j]>pn.mxp[j])
                        ret+=min(sqr(pt.a[j]-pn.mxp[j]),sqr(pt.a[j]-pn.mnp[j]));
        return ret;
}
qword get_dis(point &p1,point &p2)
{
        qword ret=0;
        for (int i=0;i<m;i++)
                ret+=sqr(p1.a[i]-p2.a[i]);
        return ret;
}
int topt=0;
void Build_kdt(int &now,int l,int r,int d)
{
        if (l>r)return;
           now=++topt;
        int i,j;
        for (j=0;j<m;j++)kdt[now].mxp[j]=-INF,kdt[now].mnp[j]=INF;
        for (i=l;i<=r;i++)
                for (j=0;j<m;j++)
                {
                        kdt[now].mxp[j]=max(kdt[now].mxp[j],pl[i].a[j]);
                        kdt[now].mnp[j]=min(kdt[now].mnp[j],pl[i].a[j]);
                }
/*        double ave[MAXM];
        double sqv[MAXM];
        memset(ave,0,sizeof(ave));
        memset(sqv,0,sizeof(sqv));
        for (i=l;i<=r;i++)
                for (j=0;j<m;j++)
                        ave[j]+=pl[i].a[j];
        for (j=0;j<m;j++)
                ave[j]/=(r-l+1);
        for (i=l;i<=r;i++)
                for (j=0;j<m;j++)
                        sqv[j]+=sqr(pl[i].a[j]-ave[j]);
        kdt[now].dd=0;
        for (j=0;j<m;j++)
                if (sqv[j]>sqv[kdt[now].dd])
                        kdt[now].dd=j;*/
        kdt[now].dd=d;
        switch (kdt[now].dd)
        {
                case 0:nth_element(&pl[l],&pl[(l+r)>>1],&pl[r+1],cmp_0);break;
                case 1:nth_element(&pl[l],&pl[(l+r)>>1],&pl[r+1],cmp_1);break;
                case 2:nth_element(&pl[l],&pl[(l+r)>>1],&pl[r+1],cmp_2);break;
                case 3:nth_element(&pl[l],&pl[(l+r)>>1],&pl[r+1],cmp_3);break;
                case 4:nth_element(&pl[l],&pl[(l+r)>>1],&pl[r+1],cmp_4);break;
        }
        kdt[now].ptr=(l+r)>>1;
        Build_kdt(kdt[now].ch[0],l,((r+l)>>1)-1,(d+1)%m);
        Build_kdt(kdt[now].ch[1],((r+l)>>1)+1,r,(d+1)%m);
}
point h[MAXN];
int atot;
int toph=0;
void search_point(int now,point &pt)
{
        if (!now)return ;
        qword cdis=get_dis(pt,pl[kdt[now].ptr]);
        if (toph<atot || cdis<h[0].dis)
        {
                if (toph==atot)pop_heap(&h[0],&h[toph--],cmp_d);
                h[toph]=pl[kdt[now].ptr];
                h[toph].dis=cdis;
                push_heap(&h[0],&h[++toph],cmp_d);
        }
        int t;
        if (get_dis(pt,kdt[kdt[now].ch[0]]) < get_dis(pt,kdt[kdt[now].ch[1]]))
                t=0;
        else
                t=1;
        search_point(kdt[now].ch[t],pt);
        if (toph<atot || get_dis(pt,kdt[kdt[now].ch[t^1]]) < h[0].dis)
        {
                search_point(kdt[now].ch[t^1],pt);
        }
}
int main()
{
    //    freopen("input.txt","r",stdin);
        //freopen("output.txt","w",stdout);
        int i,j,k,x,y,z;
        int root=0;
        while (~scanf("%d%d",&n,&m))
        {
                for (i=0;i<n;i++)
                        for (j=0;j<m;j++)
                                scanf("%d",&pl[i].a[j]);
                Build_kdt(root,0,n-1,0);
                int q;
                scanf("%d",&q);
                point pt;
                for (i=0;i<q;i++)
                {
                        for (j=0;j<m;j++)
                                scanf("%d",&pt.a[j]);
                        scanf("%d",&atot);
                        search_point(root,pt);
                        printf("the closest %d points are:\n",atot);
                        while (toph)
                        {
                                pop_heap(&h[0],&h[toph--],cmp_d);
                        }
                        for (j=0;j<atot;j++)
                                h[j].pm2();
                }
        }
}
时间: 2024-10-14 20:11:46

bzoj 3053 HDU 4347 : The Closest M Points kd树的相关文章

hdu 4347 The Closest M Points (kd树)

hdu 4347 题意: 求k维空间中离所给点最近的m个点,并按顺序输出  . 解法: kd树模板题 . 不懂kd树的可以先看看这个 . 不多说,上代码 . 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 #include <cstring> 6 #include <queue> 7 #include <s

HDU 4347 - The Closest M Points - [KDTree模板题]

本文参考: https://www.cnblogs.com/GerynOhenz/p/8727415.html kuangbin的ACM模板(新) 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4347 Problem Description The course of Software Design and Development Practice is objectionable. ZLC is facing a serious problem

数据结构(KD树):HDU 4347 The Closest M Points

The Closest M Points Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 98304/98304 K (Java/Others)Total Submission(s): 3285    Accepted Submission(s): 1201 Problem Description The course of Software Design and Development Practice is objection

HDU 4347 The Closest M Points (kdTree)

赤果果的kdTree. 传送门:http://www.cnblogs.com/v-July-v/archive/2012/11/20/3125419.html 其实就是二叉树的变形 #include<bits/stdc++.h> using namespace std; const int maxn = 5e4+6,K = 5; #define squ(x) ((x)*(x)) int k,n,idx; struct Point { int x[K]; bool operator <(c

The Closest M Points//kd树+优先队列

题目 The Closest M Points Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 98304/98304 K (Java/Others) Total Submission(s): 7570 Accepted Submission(s): 2378 Problem Description The course of Software Design and Development Practice is objectionab

【HDOJ】4347 The Closest M Points

居然是KD解. 1 /* 4347 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string> 5 #include <map> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <vector> 10 #include <deque> 11 #i

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 lo

【BZOJ】【3053】The Closest M Points

KD-Tree 题目大意:K维空间内,与给定点欧几里得距离最近的 m 个点. KD树啊……还能怎样啊……然而扩展到k维其实并没多么复杂?除了我已经脑补不出建树过程……不过代码好像变化不大>_> 然而我WA了...为什么呢...我也不知道…… 一开始我的Push_up是这么写的: inline void Push_up(int o){ rep(i,k){ if (L) t[o].mn[i]=min(t[o].mn[i],t[L].mn[i]),t[o].mx[i]=max(t[o].mx[i],

【BZOJ 3053】 The Closest M Points

3053: The Closest M Points Time Limit: 10 Sec Memory Limit: 128 MB Submit: 376 Solved: 146 [Submit][Status][Discuss] Description The course of Software Design and Development Practice is objectionable. ZLC is facing a serious problem .There are many