同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; struct Ans { int p[KD]; db d; }ans[10]; int sqr(const int &x){return x*x;} struct Node { int minn[KD],maxx[KD],p[KD]; int ch[2]; void Init() { for(int i=0;i<kd;++i) minn[i]=maxx[i]=p[i]; } db Dis() { db t=0; for(int i=0;i<kd;++i) { t+=(db)sqr(max(0,minn[i]-qp[i])); t+=(db)sqr(max(0,qp[i]-maxx[i])); } return sqrt(t); } }T[N<<1]; void Update(int rt) { for(int i=0;i<2;++i) if(T[rt].ch[i]) for(int j=0;j<kd;++j) { T[rt].minn[j]=min(T[rt].minn[j],T[T[rt].ch[i]].minn[j]); T[rt].maxx[j]=max(T[rt].maxx[j],T[T[rt].ch[i]].maxx[j]); } } db Dis(int a[],int b[]) { db t=0; for(int i=0;i<kd;++i) t+=(db)sqr(a[i]-b[i]); return sqrt(t); } bool operator < (const Node &a,const Node &b){return a.p[dn]<b.p[dn];} int Buildtree(int l=1,int r=n,int d=0) { dn=d; int m=(l+r>>1); nth_element(T+l,T+m,T+r+1); T[m].Init(); if(l!=m) T[m].ch[0]=Buildtree(l,m-1,(d+1)%kd); if(m!=r) T[m].ch[1]=Buildtree(m+1,r,(d+1)%kd); Update(m); return m; } void Query(int rt=root) { db t=Dis(T[rt].p,qp); for(int i=0;i<K;++i) if(t<ans[i].d) { for(int j=K-1;j>=i+1;--j) ans[j]=ans[j-1]; ans[i].d=t; memcpy(ans[i].p,T[rt].p,sizeof(T[rt].p)); break; } db dd[2]; for(int i=0;i<2;i++) if(T[rt].ch[i]) dd[i]=T[T[rt].ch[i]].Dis(); else dd[i]=INF; bool f=(dd[0]<=dd[1]); if(dd[!f]<ans[K-1].d && T[rt].ch[!f]) Query(T[rt].ch[!f]); if(dd[f]<ans[K-1].d && T[rt].ch[f]) Query(T[rt].ch[f]); } int q; int main() { // freopen("bzoj3053.in","r",stdin); // freopen("bzoj3053.out","w",stdout); while(scanf("%d%d",&n,&kd)!=EOF) { for(int i=1;i<=n;++i) for(int j=0;j<kd;++j) scanf("%d",&T[i].p[j]); Buildtree(); root=(1+n>>1); scanf("%d",&q); for(;q;--q) { for(int i=0;i<kd;++i) scanf("%d",&qp[i]); scanf("%d",&K); for(int i=0;i<K;++i) ans[i].d=INF; Query(); printf("the closest %d points are:\n",K); for(int i=0;i<K;++i) { for(int j=0;j<kd-1;++j) printf("%d ",ans[i].p[j]); printf("%d\n",ans[i].p[kd-1]); } } for(int i=1;i<=n;++i) T[i].ch[0]=T[i].ch[1]=0; } return 0; }
时间: 2024-10-31 03:21:26