首先是变成k维了。其次是求欧几里得距离。再其次是求m邻近点。怎么求m邻近点呢?我们开一个大根堆(优先队列)。先扔进去m个inf。然后每次查询的时候,用所得答案与大根堆的堆顶比较,如果更小,就弹出堆顶,并放进新答案。最后倒序输出这m个点。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x7f7f7f7f
#define N 50010
#define pa pair<int,int>
inline 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 n,m,K,rt=0,D,ans[15];
inline int sqr(int x){return x*x;}
struct point{
int d[5];
int& operator[](int x){return d[x];}
friend bool operator<(point a,point b){return a[D]<b[D];}
friend int dis(point a,point b){
int res=0;for(int i=0;i<K;++i) res+=sqr(b[i]-a[i]);return res;
}
}P[N],T;
struct node{
point x;int lc,rc,mx[5],mn[5];
}tr[N];
priority_queue<pa,vector<pa>,less<pa> >q;
inline void update(int p){
int l=tr[p].lc,r=tr[p].rc;
for(int i=0;i<K;++i){
if(l){
tr[p].mn[i]=min(tr[p].mn[i],tr[l].mn[i]);
tr[p].mx[i]=max(tr[p].mx[i],tr[l].mx[i]);
}if(r){
tr[p].mn[i]=min(tr[p].mn[i],tr[r].mn[i]);
tr[p].mx[i]=max(tr[p].mx[i],tr[r].mx[i]);
}
}
}
inline void build(int &p,int l,int r,int op){
int mid=l+r>>1;p=mid;D=op;tr[p].lc=tr[p].rc=0;
nth_element(P+l,P+mid,P+r+1);tr[p].x=P[mid];
for(int i=0;i<K;++i) tr[p].mn[i]=tr[p].mx[i]=tr[p].x[i];
if(l<mid) build(tr[p].lc,l,mid-1,(op+1)%K);
if(r>mid) build(tr[p].rc,mid+1,r,(op+1)%K);
update(p);
}
inline int calcmn(int p){
if(!p) return inf;int res=0;
for(int i=0;i<K;++i){
if(T[i]<tr[p].mn[i]) res+=sqr(tr[p].mn[i]-T[i]);
if(T[i]>tr[p].mx[i]) res+=sqr(tr[p].mx[i]-T[i]);
}return res;
}
inline void ask(int p){
int tmp=dis(tr[p].x,T);
if(tmp<q.top().first){
q.pop();q.push(make_pair(tmp,p));
}int dl=calcmn(tr[p].lc),dr=calcmn(tr[p].rc);
if(dl<dr){
if(dl<q.top().first) ask(tr[p].lc);
if(dr<q.top().first) ask(tr[p].rc);
}else{
if(dr<q.top().first) ask(tr[p].rc);
if(dl<q.top().first) ask(tr[p].lc);
}
}
int main(){
// freopen("a.in","r",stdin);
while(~scanf("%d%d",&n,&K)){
for(int i=1;i<=n;++i)
for(int k=0;k<K;++k) P[i][k]=read();
build(rt,1,n,0);int owo=read();
while(owo--){
for(int k=0;k<K;++k) T[k]=read();m=read();
for(int i=1;i<=m;++i) q.push(make_pair(inf,0));
ask(rt);printf("the closest %d points are:\n",m);
for(int i=m;i>=1;--i) ans[i]=q.top().second,q.pop();
for(int i=1;i<=m;++i)
for(int k=0;k<K;++k){
printf("%d",tr[ans[i]].x[k]);
putchar(k==K-1?'\n':' ');
}
}
}return 0;
}