K-D树问题 HDU 4347

K-D树可以看看这个博客写的真心不错!这里存个版

http://blog.csdn.net/zhjchengfeng5/article/details/7855241

HDU 4349

#include <map>
//KD树学习http://blog.csdn.net/zhjchengfeng5/article/details/7855241
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
#define MAXN 100010
const LL INF = LONG_LONG_MAX;
struct node
{
    LL pos[10];
    int id;
}tree[MAXN],op,point;
int split[MAXN],N,now,demension;
bool used[MAXN];
LL ans,id;
double var[10];
bool cmp(const node &a,const node &b)
{
    return a.pos[split[now]] < b.pos[split[now]];
}
void build(int L,int R)
{
    if (L > R) return;
    int mid = (L + R) / 2;
    //求出每一唯上的方差
    for (int pos = 0 ; pos < demension ; pos++)
    {
        double avg = var[pos] = 0;
        for (int i = L ; i <= R; i++)
            avg += tree[i].pos[pos];
        avg /= (R - L + 1);
        for (int i = L ; i <= R; i++)
            var[pos] += (tree[i].pos[pos] - avg) * (tree[i].pos[pos] - avg);
        var[pos] /= (R - L + 1);
    }
    //找到方差最大的那一个唯独
    split[now = mid] = 0;
    for (int i = 1; i < demension ; i++)
        if (var[split[mid]] < var[i]) split[mid] = i;
    nth_element(tree + L ,tree + mid,tree + R + 1,cmp);
    build(L,mid - 1);
    build(mid + 1,R);
}
void query(int L,int R)
{
    if (L > R) return;
    int mid = (L + R) / 2;
    LL dis = 0;
    //求出目标点到当前根节点的距
    for (int i = 0 ; i < demension ; i++)
        dis += (op.pos[i] - tree[mid].pos[i]) * (op.pos[i] - tree[mid].pos[i]);
    //if (dis == 0) dis = INF;
    //printf("%lld\n",dis);
    //如果当前节点能够用来更新最近距离并且dis<ans
    if (!used[tree[mid].id] && dis < ans)
    {
        ans = dis;
        id = tree[mid].id;
        point = tree[mid];
    }
    //计算op到分裂平面的距离
    LL radius = (op.pos[split[mid]] - tree[mid].pos[split[mid]]) *
    (op.pos[split[mid]] - tree[mid].pos[split[mid]]);
    //对子区间进行查询
    if (op.pos[split[mid]] < tree[mid].pos[split[mid]])
    {
        query(L,mid - 1);
        if (radius <= ans) query(mid + 1,R);
    }
    else
    {
        query(mid + 1,R);
        if (radius <= ans) query(L,mid - 1);
    }
}
node ret[20];
int main()
{
   // freopen("sample.txt","r",stdin);
    while (scanf("%d%d",&N,&demension) != EOF)
    {
        for (int i = 1; i <= N; i++)
            for (int j = 0 ;j < demension ; j++)
            scanf("%lld",&tree[i].pos[j]);
        for (int i = 1; i <= N; i++) tree[i].id = i;
        build(1,N);
        int T;
        scanf("%d",&T);
        for (int i = 1; i <= T; i++)
        {
            for (int j = 0;  j < demension ; j++)
                scanf("%lld",&op.pos[j]);
            //printf("%lld %lld\n",op.pos[0],op.pos[1]);
            memset(used,false,sizeof(used));
            int m;
            scanf("%d",&m);
            for (int j = 0 ; j < m ; j++)
            {
                ans = INF;
                query(1,N);
                ret[j] = point;
                //printf("%lld\n",id);
                used[id] = true;
            }
            printf("the closest %d points are:\n",m);
            for (int j = 0 ; j < m ; j++)
            {
                printf("%lld",ret[j].pos[0]);
                for (int k = 1; k < demension ; k++)
                    printf(" %lld",ret[j].pos[k]);
                putchar(‘\n‘);
            }
        }
    }
    return 0;
}

  

时间: 2024-12-06 16:00:23

K-D树问题 HDU 4347的相关文章

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

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

【线段树】hdu 1754 I Hate It

[线段树]hdu 1754 I Hate It 题目链接:hdu 1754 I Hate It 题目大意 N个学生的初始成绩已知,操作m次,每次要么将第i个学生的成绩更新,要么查找区间[x,y]的最大成绩. 很显然这是一道线段树,点修改.区间查询,笔者第三道线段树,完全自己敲的,直接AC~(≧▽≦)/~啦啦啦. 如果单纯查找区间最大值,时间复杂度O(N),而线段树O(logN),当查询的次数非常多时,显然后者更高效! 说一下思路 线段树的点修改[点更新]:直接将叶节点更新为输入的数据,对照"敌兵

【线段树】hdu 1556 Color the ball

[线段树]hdu 1556 Color the ball 题目链接:hdu 1556 Color the ball 题目大意 给你N个气球,不断刷新指定区间的颜色,刷新N次,最后输出每一个气球的刷新次数. 上一篇文章是线段树的点修改.区间查询: 这篇文章是线段树的区间修改.点查询: 说一下思路 线段树的区间修改:利用线段树的区间查询,查询到叶节点segTree[root].sum++,而如果对区间进行多次点修改的话,注定超时 线段树的点查询:以为用之前的区间查询就可以了,实际上还是有改变,因为原

【线段树】HDU 1394 Minimum Inversion Number

minimum inversion number:最小逆序数 Minimum Inversion NumberTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 9367    Accepted Submission(s): 5754 Problem Description The inversion number of a given nu

【线段树】hdu 1166 敌兵布阵

[线段树]hdu 1166 敌兵布阵 题目链接:hdu 1166 敌兵布阵 题目大意 C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况.由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视. 中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时

【哈弗曼树】HDU 5350 MZL&#39;s munhaff function

通道 题意:根据那个递推式,找找规律即可. 代码: #include <cstdio> #include <cstring> #include <vector> #include <queue> #include <algorithm> using namespace std; typedef long long ll; inline bool rd(int &ret) { char c; int sgn; if(c = getchar(

【线段树】 HDU 5025 A Corrupt Mayor&#39;s Performance Art

更新区间内颜色 输出区间内的颜色总数 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <string> #include <iostream> #include <algorithm> #include <sstream> #include <math.h> using namespace std; #include <

【线段树】HDU 3397 Sequence operation 区间合并

操作 Change operations: 0 a b change all characters into '0's in [a , b] 1 a b change all characters into '1's in [a , b] 2 a b change all '0's into '1's and change all '1's into '0's in [a, b] Output operations: 3 a b output the number of '1's in [a,