BZOJ3053 - The Closest M Points
Description
给出
Solution
跟普通的k-d树差不多,就是要开一个容量为
Code
这个代码目前RE!又是对拍全过然后GG…
//The Closest M Points
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
inline char gc()
{
static char now[1<<16],*S,*T;
if(S==T) {T=(S=now)+fread(now,1,1<<16,stdin); if(S==T) return EOF;}
return *S++;
}
inline int read()
{
int x=0,f=1; char ch=gc();
while((ch<'0'||'9'<ch)&&ch!=EOF) {if(ch=='-') f=-1; ch=gc();}
while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int const N=5e4+10;
int const INF=0x7FFFFFFF;
int n,K;
#define ch1 ch[p][0]
#define ch2 ch[p][1]
int rt,ch[N][2];
struct point{int c[5];} pt[N];
struct zone{int c1[5],c2[5];} zn[N];
int D; bool cmpPt(point x,point y) {return x.c[D]<y.c[D];}
void update(int p)
{
for(int k=0;k<K;k++)
{
zn[p].c1[k]=min(pt[p].c[k],min(zn[ch1].c1[k],zn[ch2].c1[k]));
zn[p].c2[k]=max(pt[p].c[k],max(zn[ch1].c2[k],zn[ch2].c2[k]));
}
}
void build(int &p,int L,int R,int k0)
{
p=L+R>>1; D=k0;
nth_element(pt+L,pt+p,pt+R+1,cmpPt);
if(L<p) build(ch[p][0],L,p-1,(k0+1)%K);
if(p<R) build(ch[p][1],p+1,R,(k0+1)%K);
update(p);
}
point A;
int dst(point B)
{
int res=0; if(B.c[0]==INF) return INF;
for(int k=0;k<K;k++) res+=(A.c[k]-B.c[k])*(A.c[k]-B.c[k]);
return res;
}
int dst(zone z)
{
int res=0;
for(int k=0;k<K;k++)
if(A.c[k]<z.c1[k]) res+=(z.c1[k]-A.c[k])*(z.c1[k]-A.c[k]);
else if(z.c2[k]<A.c[k]) res+=(A.c[k]-z.c2[k])*(A.c[k]-z.c2[k]);
return res;
}
#define pInt pair<int,int>
priority_queue< pInt,vector<pInt>,less<pInt> > q;
void query(int p)
{
if(dst(pt[p])<dst(pt[q.top().second])) q.pop(),q.push(make_pair(dst(pt[p]),p));
int p0=q.top().second;
if(ch1&&dst(zn[ch1])<dst(pt[p0])) query(ch1);
if(ch2&&dst(zn[ch2])<dst(pt[p0])) query(ch2);
}
int ans[20];
int main()
{
while(true)
{
n=read(),K=read(); if(n==0) break;
for(int k=0;k<K;k++) pt[0].c[k]=INF,zn[0].c1[k]=INF,zn[0].c2[k]=-INF;
for(int i=1;i<=n;i++)
for(int k=0;k<K;k++) pt[i].c[k]=read();
build(rt,1,n,0);
int t=read();
while(t--)
{
for(int k=0;k<K;k++) A.c[k]=read();
int m=read(); for(int i=1;i<=m;i++) q.push(make_pair(INF,0));
query(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 ",pt[ans[i]].c[k]);
printf("\n");
}
while(!q.empty()) q.pop();
}
}
return 0;
}
P.S.
我好菜啊…