题目大意:K维空间内,与给定点欧几里得距离最近的 m 个点。
KD树啊……还能怎样啊……然而扩展到k维其实并没多么复杂?除了我已经脑补不出建树过程……不过代码好像变化不大>_>
然而我WA了。。。为什么呢。。。我也不知道……
一开始我的Push_up是这么写的:
inline void Push_up(int o){ rep(i,k){ if (L) t[o].mn[i]=min(t[o].mn[i],t[L].mn[i]),t[o].mx[i]=max(t[o].mx[i],t[L].mx[i]); if (R) t[o].mx[i]=min(t[o].mn[i],t[R].mn[i]),t[o].mx[i]=max(t[o].mx[i],t[R].mx[i]); } }
就是如果没有右儿子,就不用它更新了……
然而我改成zyf的这样:(t[0]初始化一下,mn都置为INF,mx都置为-INF)
inline void Push_up(int o){ rep(i,k){ t[o].mn[i]=min(t[o].mn[i],min(t[L].mn[i],t[R].mn[i])); t[o].mx[i]=max(t[o].mx[i],max(t[L].mx[i],t[R].mx[i])); } }
就过了………………
P.S.多组数据的题目,KD-Tree一定要记得清空 l 和 r ……要不然叶子节点会有一些奇怪的问题……
获得称号:
1 /************************************************************** 2 Problem: 3053 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:1364 ms 7 Memory:9088 kb 8 ****************************************************************/ 9 10 //BZOJ 3053 11 #include<queue> 12 #include<cmath> 13 #include<cstdio> 14 #include<cstring> 15 #include<cstdlib> 16 #include<iostream> 17 #include<algorithm> 18 #define rep(i,n) for(int i=0;i<n;++i) 19 #define F(i,j,n) for(int i=j;i<=n;++i) 20 #define D(i,j,n) for(int i=j;i>=n;--i) 21 #define pb push_back 22 #define sqr(x) ((x)*(x)) 23 using namespace std; 24 typedef long long LL; 25 inline int getint(){ 26 int r=1,v=0; char ch=getchar(); 27 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 28 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 29 return r*v; 30 } 31 const int N=100010,INF=1e9; 32 /*******************template********************/ 33 34 int n,k,D,root,ans[15]; 35 struct node{ 36 int d[6],mn[6],mx[6],l,r; 37 int& operator [] (int x){return d[x];} 38 void read(){rep(i,k) d[i]=getint();} 39 }t[N],tmp; 40 bool operator < (node a,node b){return a[D]<b[D];} 41 #define L t[o].l 42 #define R t[o].r 43 #define mid (l+r>>1) 44 inline void Push_up(int o){ 45 rep(i,k){ 46 t[o].mn[i]=min(t[o].mn[i],min(t[L].mn[i],t[R].mn[i])); 47 t[o].mx[i]=max(t[o].mx[i],max(t[L].mx[i],t[R].mx[i])); 48 } 49 } 50 int build(int l,int r,int dir){ 51 D=dir; 52 nth_element(t+l,t+mid,t+r+1); 53 rep(i,k) t[mid].mn[i]=t[mid].mx[i]=t[mid][i]; 54 t[mid].l=l<mid ? build(l,mid-1,(dir+1)%k) : 0; 55 t[mid].r=mid<r ? build(mid+1,r,(dir+1)%k) : 0; 56 Push_up(mid); 57 return mid; 58 } 59 inline int getdis(int o){ 60 if (!o) return INF; 61 int ans=0; 62 rep(i,k) if (tmp[i]<t[o].mn[i]) ans+=sqr(t[o].mn[i]-tmp[i]); 63 rep(i,k) if (tmp[i]>t[o].mx[i]) ans+=sqr(tmp[i]-t[o].mx[i]); 64 return ans; 65 } 66 inline int dis(node a,node b){ 67 int ans=0; 68 rep(i,k) ans+=sqr(a[i]-b[i]); 69 return ans; 70 } 71 typedef pair<int,int> pii; 72 priority_queue<pii>Q; 73 #define mp make_pair 74 #define X first 75 #define Y second 76 void query(int o){ 77 int dl=getdis(L),dr=getdis(R),d0=dis(t[o],tmp); 78 if (d0<Q.top().X){Q.pop(); Q.push(mp(d0,o));} 79 if (dl<dr){ 80 if (dl<Q.top().X) query(L); 81 if (dr<Q.top().X) query(R); 82 }else{ 83 if (dr<Q.top().X) query(R); 84 if (dl<Q.top().X) query(L); 85 } 86 } 87 int main(){ 88 #ifndef ONLINE_JUDGE 89 freopen("3053.in","r",stdin); 90 freopen("3053.out","w",stdout); 91 #endif 92 rep(i,5) t[0].mn[i]=INF,t[0].mx[i]=-INF; 93 while(scanf("%d%d",&n,&k)!=EOF){ 94 F(i,1,n) rep(j,k) t[i][j]=getint(); 95 root=build(1,n,0); 96 int T=getint(); 97 while(T--){ 98 rep(j,k) tmp[j]=getint(); 99 n=getint(); 100 printf("the closest %d points are:\n",n); 101 F(i,1,n) Q.push(mp(INF,0)); 102 query(root); 103 D(i,n,1) ans[i]=Q.top().Y,Q.pop(); 104 F(i,1,n) rep(j,k) 105 printf("%d%c",t[ans[i]][j],j!=k-1?' ':'\n'); 106 } 107 } 108 return 0; 109 }