BZOJ 3053(The Closest M Points-N維KD_Tree),points-nkd_tree
3053: The Closest M PointsTime Limit: 10 Sec Memory Limit: 128 MB
Submit: 442 Solved: 173
[Submit][Status][Discuss]Description
The course of Software Design and Development Practice is objectionable. ZLC is facing a serious problem .There are many points in K-dimensional space .Given a point. ZLC need to find out the closest m points. Euclidean distance is used as the distance metric between two points. The Euclidean distance between points p and q is the length of the line segment connecting them.In Cartesian coordinates, if p = (p1, p2,..., pn) and q = (q1, q2,..., qn) are two points in Euclidean n-space, then the distance from p to q, or from q to p is given by:
D(p,q)=D(q,p)=sqrt((q1-p1)^2+(q2-p2)^2+(q3-p3)^2…+(qn-pn)^2
Can you help him solve this problem?
軟工學院的課程很討厭!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,所以就麻煩你幫忙解決一下了……
【Input】
第一行,兩個非負整數:點數n(1 <= n <= 50000),和維度數k(1 <= k <= 5)。
接下來的n行,每行k個整數,代表一個點的座標。
接下來一個正整數:給定的詢問數量t(1 <= t <= 10000)
下面2*t行:
第一行,k個整數:給定點的座標
第二行:查詢最近的m個點(1 <= m <= 10)
所有座標的絕對值不超過10000。
有多組資料!
【Output】
對於每個詢問,輸出m+1行:
第一行:"the closest m points are:" m為查詢中的m
接下來m行每行代表一個點,按照從近到遠排序。
保證方案唯一,下面這種情況不會出現:
2 2
1 1
3 3
1
2 2
1
Input
In the first line of the text file .there are two non-negative integers n and K. They denote respectively: the number of points, 1 <= n <= 50000, and the number of Dimensions,1 <= K <= 5. In each of the following n lines there is written k integers, representing the coordinates of a point. This followed by a line with one positive integer t, representing the number of queries,1 <= t <=10000.each query contains two lines. The k integers in the first line represent the given point. In the second line, there is one integer m, the number of closest points you should find,1 <= m <=10. The absolute value of all the coordinates will not be more than 10000.
There are multiple test cases. Process to end of file.
Output
For each query, output m+1 lines:
The first line saying :”the closest m points are:” where m is the number of the points.
The following m lines representing m points ,in accordance with the order from near to far
It is guaranteed that the answer can only be formed in one ways. The distances from the given point to all the nearest m+1 points are different. That means input like this:
2 2
1 1
3 3
1
2 2
1
will not exist.
Sample Input3 2
1 1
1 3
3 4
2
2 3
2
2 3
1
Sample Outputthe closest 2 points are:
1 3
3 4
the closest 1 points are:
1 3
HINT
Source
k-d tree
[Submit][Status][Discuss]
N維KD_Tree
注意用cin在Bzoj上RE
Python測資料部分,和std對拍都對
import randomimport sys#os.mknod("data.txt")fp=open("bzoj3053_2.in",'w')sys.stdout=fpmaxxi=10000n=50000k=5print(n,k)for i in range(0,n): for j in range(0,k): print(random.randint(-maxxi,maxxi+1),end=' ') print('')t=100print(t)for i in range(0,t): for j in range(0,k): print(random.randint(-maxxi,maxxi+1),end=' ') print('') print(random.randint(1,10))fp.close()
#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<functional>#include<iostream>#include<cmath>#include<queue>using namespace std;#define For(i,n) for(int i=1;i<=n;i++)#define Fork(i,k,n) for(int i=k;i<=n;i++)#define Rep(i,n) for(int i=0;i<n;i++)#define ForD(i,n) for(int i=n;i;i--)#define RepD(i,n) for(int i=n;i>=0;i--)#define Forp(x) for(int p=pre[x];p;p=next[p])#define Forpiter(x) for(int &p=iter[x];p;p=next[p]) #define Lson (x<<1)#define Rson ((x<<1)+1)#define MEM(a) memset(a,0,sizeof(a));#define MEMI(a) memset(a,127,sizeof(a));#define MEMi(a) memset(a,128,sizeof(a));#define INF (2139062143)#define F (100000007)#define MAXN (100000+10)#define MAXK (5)#define MAXT (10000+10)#define MAXXi (10000)#define MAXM (10+10) typedef long long ll;ll mul(ll a,ll b){return (a*b)%F;}ll add(ll a,ll b){return (a+b)%F;}ll sub(ll a,ll b){return (a-b+(a-b)/F*F+F)%F;}void upd(ll &a,ll b){a=(a%F+b%F)%F;}int n,K,t,m;int cmp_d=0;class node{public:int x[MAXK];int l,r,minv[MAXK],maxv[MAXK];int& operator[](int i){return x[i];} node(){}node(int a[]){memcpy(x,a,sizeof(int)*K);l=r=0;Rep(i,K) minv[i]=maxv[i]=x[i];}void read(){Rep(i,K) scanf("%d",&x[i]);l=r=0;Rep(i,K) minv[i]=maxv[i]=x[i];}void print(){printf("%d",x[0]);For(i,K-1) printf(" %d",x[i]);printf("\n"); }};priority_queue< pair<int,int> , vector< pair<int,int> > , greater<vector< pair<int,int> >::value_type> > q,qans;int sqr(int x){return x*x;}int dis(node a,node b){int ans=0;Rep(i,K) ans+=sqr(a.x[i]-b.x[i]);return ans;}int dis2(node p,node a) // 點p和方形地區a的歐幾裡德距離 {int ans=0;Rep(i,K){if (p.x[i]<a.minv[i]) ans+=sqr(a.minv[i]-p.x[i]);elseif (p.x[i]>a.maxv[i]) ans+=sqr(p.x[i]-a.maxv[i]);}return ans;}int cmp(node a,node b){return a[cmp_d]<b[cmp_d];}class KD_Tree{public:node a[MAXN];void update(node& o){if (o.l){node p=a[o.l];Rep(i,K) o.minv[i]=min(o.minv[i],p.minv[i]);Rep(i,K) o.maxv[i]=max(o.maxv[i],p.maxv[i]);}if (o.r){node p=a[o.r];Rep(i,K) o.minv[i]=min(o.minv[i],p.minv[i]);Rep(i,K) o.maxv[i]=max(o.maxv[i],p.maxv[i]);}}int build(int L,int R,int nowd){int m=(L+R)>>1;cmp_d=nowd;nth_element(a+L,a+m,a+R+1,cmp);if (L^m) a[m].l=build(L,m-1,(nowd+1)%K);if (R^m) a[m].r=build(m+1,R,(nowd+1)%K);update(a[m]);return m;} int root;void _build(int L,int R,int nowd) //1-n的節點 至少為1 {root=build(L,R,nowd);}node _p;int _ans;void ask_min_dis(int o){if (o==0) return;q.push(make_pair(dis2(_p,a[o]),o));qans.push(make_pair(dis(_p,a[o]),o));while (m&&!q.empty()){o=q.top().second; if (o==0) return;//cout<<q.size()<<':'<<o<<endl;int nowdis=q.top().first;while (m&&!qans.empty()&&nowdis>=qans.top().first){a[qans.top().second].print();qans.pop();m--;}if (m==0) return ;q.pop();int ans1=a[o].l ? dis2(_p,a[a[o].l]) : INF;// 點p到地區內任意一點的距離的最小值int ans2=a[o].r ? dis2(_p,a[a[o].r]) : INF;pair<int,int> p1=make_pair(ans1,a[o].l);pair<int,int> p2=make_pair(ans2,a[o].r);if (ans1<ans2) {if(ans1<_ans) qans.push( make_pair(dis(_p,a[a[o].l]),a[o].l) ),q.push(p1);if(ans2<_ans) qans.push( make_pair(dis(_p,a[a[o].r]),a[o].r) ),q.push(p2);}else {if(ans2<_ans) qans.push( make_pair(dis(_p,a[a[o].r]),a[o].r) ),q.push(p2);if(ans1<_ans) qans.push( make_pair(dis(_p,a[a[o].l]),a[o].l) ),q.push(p1);}}while (m&&!qans.empty()){a[qans.top().second].print();qans.pop();m--;}}int _ask(node p){while(!q.empty()) q.pop();while(!qans.empty()) qans.pop();_p=p;_ans=INF;ask_min_dis(root);return _ans; }}S;int main(){//freopen("bzoj3053_2.in","r",stdin);//freopen("bzoj3053.out","w",stdout);while(cin>>n>>K){cmp_d=0;For(i,n){S.a[i].read();} S._build(1,n,0);cin>>t;For(i,t){node p;p.read();scanf("%d",&m);printf("the closest %d points are:\n",m);S._ask(p);} }return 0;}