【BZOJ3053】The Closest M Points KDtree 好模板一只【数组版!!!】

题解:多维的估价跟二维一样,每一维的贡献跟二维的‘x’、‘y’完全相同。

真不明白不会的是怎么想的,有区别么?!!

细节:

妈蛋的多组数据!调了好久啊、

然后行末还不能有空格,否则PE

除去这些,我是1A。。

可惜没有“除去”这一说。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 50100
#define K 10
#define inf 0x3f3f3f3f
using namespace std;
int judge,n,m,q;
struct Point
{
	int c[K];
	bool operator < (const Point &a)const{return c[judge]<a.c[judge];}
	int d(Point &a)
	{
		int ret=0;
		for(int i=0;i<m;i++)ret+=(c[i]-a.c[i])*(c[i]-a.c[i]);
		return ret;
	}
}P[N];
struct ANS
{
	int x;
	Point p;
	bool operator < (const ANS &a)const {return x<a.x;}
}ans[15];
struct KDT
{
	int son[N][2],cnt;
	Point c[N][2];
	void init()
	{
		cnt=0;
		memset(son,0,sizeof(son));
	}
	int newnode(Point &p){cnt++,c[cnt][0]=c[cnt][1]=p;return cnt;}
	void update(int f)
	{
		int i,s;
		if(son[f][0])
		{
			s=son[f][0];
			for(i=0;i<m;i++)
				c[f][0].c[i]=min(c[f][0].c[i],c[s][0].c[i]),
				c[f][1].c[i]=max(c[f][1].c[i],c[s][1].c[i]);
		}
		if(son[f][1])
		{
			s=son[f][1];
			for(i=0;i<m;i++)
				c[f][0].c[i]=min(c[f][0].c[i],c[s][0].c[i]),
				c[f][1].c[i]=max(c[f][1].c[i],c[s][1].c[i]);
		}
	}
	int mindis(int f,Point &p)
	{
		int ret=0,i;
		for(i=0;i<m;i++)
		{
			if(p.c[i]<c[f][0].c[i])ret+=(c[f][0].c[i]-p.c[i])*(c[f][0].c[i]-p.c[i]);
			else if(c[f][1].c[i]<p.c[i])ret+=(c[f][1].c[i]-p.c[i])*(c[f][1].c[i]-p.c[i]);
		}
		return ret;
	}
	int build(int l,int r,int jd=0)
	{
		int mid=l+r>>1,i;
		judge=jd;
		jd=jd+1>=m?jd-m+1:jd+1;
		nth_element(P+l,P+mid,P+r+1);
		int t=0;
		if(l<mid)t=build(l,mid-1,jd);
		int x=newnode(P[mid]);son[x][0]=t;
		if(mid<r)son[x][1]=build(mid+1,r,jd);
		update(x);
		return x;
	}
	void query(int f,Point &p,int rank)
	{
		int Dis[3],i;
		Dis[2]=P[f].d(p);
		if(ans[rank-1].x>Dis[2])ans[rank-1].x=Dis[2],ans[rank-1].p=P[f],sort(ans,ans+rank);

		Dis[0]=Dis[1]=0;
		if(son[f][0])Dis[0]=mindis(son[f][0],p);
		if(son[f][1])Dis[1]=mindis(son[f][1],p);
		int t=Dis[0]>Dis[1];
		if(son[f][t]&&Dis[t]<ans[rank-1].x)query(son[f][t],p,rank);
		t^=1;if(son[f][t]&&Dis[t]<ans[rank-1].x)query(son[f][t],p,rank);
	}
}kdt;
int main()
{
//	freopen("test.in","r",stdin);
	int i,j,k,root;
	Point x;
	while(~scanf("%d%d",&n,&m))
	{
		root=0;
		kdt.init();
		for(i=1;i<=n;i++)for(j=0;j<m;j++)scanf("%d",&P[i].c[j]);
		if(n)root=kdt.build(1,n);
		for(scanf("%d",&q);q--;)
		{
			for(i=0;i<m;i++)scanf("%d",&x.c[i]);scanf("%d",&k);
			for(i=0;i<15;i++)ans[i].x=inf;
			kdt.query(root,x,k);
			printf("the closest %d points are:\n",k);
			for(i=0;i<k;i++)
			{
				for(j=0;j<m-1;j++)printf("%d ",ans[i].p.c[j]);
				printf("%d\n",ans[i].p.c[m-1]);
			}
		}
	//	puts("");
	}
	return 0;
}

复制去Google翻译翻译结果

时间: 2024-11-08 22:06:03

【BZOJ3053】The Closest M Points KDtree 好模板一只【数组版!!!】的相关文章

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-tree】bzoj3053 The Closest M Points

同p2626.由于K比较小,所以不必用堆. #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; typedef double db; #define N 50001 #define INF 2147483647.0 #define KD 5//ά¶ÈÊý int qp[KD]; int n,root,kd,K; int dn;

BZOJ3053 The Closest M Points

裸的KD-tree,还是在估计要不要进入子树的时候判断一下就好了,剩下都一样 判断的方法就是看现在答案个数是否小于k,和答案是否会经过分割线. 1 /************************************************************** 2 Problem: 3053 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:2164 ms 7 Memory:3572 kb 8 ************

poj4091The Closest M Points(KD-tree)

kd-tree参考资料: http://my.oschina.net/keyven/blog/221792 http://blog.csdn.net/lsjseu/article/details/12344443 1 #include <cstdio> 2 #include <algorithm> 3 #include <queue> 4 #include <cstring> 5 using namespace std; 6 7 const int MAXD

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

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

http://www.lydsy.com/JudgeOnline/problem.php?id=3053 本来是1a的QAQ.... 没看到有多组数据啊.....斯巴达!!!!!!!!!!!!!!!!! 本题裸的kdtree,比上一题还要简单...................................... 对于当前点,判断进入左或右子树,然后看答案是否能过分割线..如果能,进入右或左子树.........并且如果答案个数小于k,也要进入.. 然后就浪吧........... #inc

【hdu4347】The Closest M Points 【KD树模板】

题意 一个k维空间,给出n个点的坐标,给出t个询问,每个询问给出一个点的坐标和一个m.对于每个询问找出跟这个点最接近的m个点 分析 kd树的模板题. 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <queue> 6 7 using namespace std; 8 typedef long long

【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

【BZOJ 3053】The Closest M Points

KDTree模板,在m维空间中找最近的k个点,用的是欧几里德距离. 理解了好久,昨晚始终不明白那些“估价函数”,后来才知道分情况讨论,≤k还是=k,在当前这一维度距离过线还是不过线,过线则要继续搜索另一个子树.还有别忘了当前这个节点! #include<cmath> #include<queue> #include<cstdio> #include<cstring> #include<algorithm> #define read(x) x=ge