看了青岛赛区的题简单学了一下kd,感觉这东西还是挺厉害的
一般kd树找最近点对最坏是O(n),但是随机情况下跑得还是很快的
kd树是一棵BST,但是每一层的关键字不同
一般写法是按照每一维轮流来,这一维小的放左子树,大的放右边的
每个节点再维护这节点所管辖的节点每一维的范围,这样基本就能做题了
kdtree一般是静态直接建好的,插入可以套一个替罪羊树重构做到logn,但是据说慢
那么怎么查询最近点呢
每到一个节点,比较通过这节点所管辖点的每一维的范围,估计出可能最小的距离
优先访问估值优的子树
可以看到查询几乎就是个搜索+剪枝,所以最坏是O(n),最远点类似
这样bzoj1941就解了
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 const int inf=1e9+7; 5 int key,dmx,dmi,root,n,x[500010],y[500010]; 6 7 struct node 8 { 9 int son[2],mi[2],mx[2],d[2]; 10 friend bool operator <(node a,node b) 11 { 12 return a.d[key]<b.d[key]; 13 } 14 friend int dis(node a,node b) 15 { 16 return abs(a.d[1]-b.d[1])+abs(a.d[0]-b.d[0]); 17 } 18 } po; 19 20 struct kdtree 21 { 22 node a[500010]; 23 void init() 24 { 25 a[0].son[0]=a[0].son[1]=0; 26 for (int i=0; i<2; i++) 27 { 28 a[0].mi[i]=inf; 29 a[0].mx[i]=-inf; 30 } 31 } 32 void update(int x) 33 { 34 int l=a[x].son[0],r=a[x].son[1]; 35 for (int i=0; i<2; i++) 36 { 37 a[x].mi[i]=min(a[x].d[i],min(a[l].mi[i],a[r].mi[i])); 38 a[x].mx[i]=max(a[x].d[i],max(a[l].mx[i],a[r].mx[i])); 39 } 40 } 41 int build(int l,int r,int cur) 42 { 43 if (l>r) return 0; 44 int m=(l+r)>>1; 45 key=cur; nth_element(a+l,a+m,a+r+1); 46 a[m].son[0]=build(l,m-1,cur^1); 47 a[m].son[1]=build(m+1,r,cur^1); 48 update(m); 49 return m; 50 } 51 int getmi(int x) 52 { 53 int s=0; 54 for (int i=0;i<2;i++) 55 s+=max(po.d[i]-a[x].mx[i],0)+max(a[x].mi[i]-po.d[i],0); 56 return s; 57 } 58 int getmx(int x) 59 { 60 int s=0; 61 for (int i=0;i<2;i++) 62 s+=max(abs(po.d[i]-a[x].mi[i]),abs(po.d[i]-a[x].mx[i])); 63 return s; 64 } 65 void askmx(int q) 66 { 67 dmx=max(dmx,dis(a[q],po)); 68 int l=a[q].son[0],r=a[q].son[1],dl=-inf,dr=-inf; 69 if (l) dl=getmx(l); 70 if (r) dr=getmx(r); 71 if (dl>dr) 72 { 73 if (dl>dmx) askmx(l); 74 if (dr>dmx) askmx(r); 75 } 76 else { 77 if (dr>dmx) askmx(r); 78 if (dl>dmx) askmx(l); 79 } 80 } 81 void askmi(int q) 82 { 83 int dd=dis(a[q],po); if (dd) dmi=min(dmi,dd); 84 int l=a[q].son[0],r=a[q].son[1],dl=inf,dr=inf; 85 if (l) dl=getmi(l); 86 if (r) dr=getmi(r); 87 if (dl<dr) 88 { 89 if (dl<dmi) askmi(l); 90 if (dr<dmi) askmi(r); 91 } 92 else { 93 if (dr<dmi) askmi(r); 94 if (dl<dmi) askmi(l); 95 } 96 } 97 } kd; 98 99 int main() 100 { 101 kd.init(); 102 scanf("%d",&n); 103 for (int i=1; i<=n; i++) 104 { 105 scanf("%d%d",&x[i],&y[i]); 106 kd.a[i].d[0]=x[i]; 107 kd.a[i].d[1]=y[i]; 108 } 109 root=kd.build(1,n,0); int ans=inf; 110 for (int i=1;i<=n;i++) 111 { 112 dmx=-inf,dmi=inf; 113 po.d[0]=x[i],po.d[1]=y[i]; 114 kd.askmx(root); kd.askmi(root); 115 ans=min(ans,dmx-dmi); 116 } 117 printf("%d\n",ans); 118 }
hdu5992要加一维价格剪枝,如果这个节点所辖节点的最小价格都比询问大就不访问了
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 typedef long long ll; 5 const int inf=1e9+7; 6 int key,root,n,m; 7 ll len; 8 ll sqr(ll x) 9 { 10 return x*x; 11 } 12 13 struct node 14 { 15 int d[3],mi[3],mx[3],son[2],id; 16 friend bool operator <(node a,node b) 17 { 18 return a.d[key]<b.d[key]; 19 } 20 friend ll dis(node a,node b) 21 { 22 return sqr(a.d[1]-b.d[1])+sqr(a.d[0]-b.d[0]); 23 } 24 } po,ans; 25 26 struct kdtree 27 { 28 node a[200010]; 29 void init() 30 { 31 a[0].son[0]=a[0].son[1]=0; 32 for (int i=0; i<3; i++) 33 { 34 a[0].mi[i]=inf; 35 a[0].mx[i]=-inf; 36 } 37 } 38 void update(int x) 39 { 40 int l=a[x].son[0],r=a[x].son[1]; 41 for (int i=0; i<3; i++) 42 { 43 a[x].mi[i]=min(a[x].d[i],min(a[l].mi[i],a[r].mi[i])); 44 a[x].mx[i]=max(a[x].d[i],max(a[l].mx[i],a[r].mx[i])); 45 } 46 } 47 int build(int l,int r,int cur) 48 { 49 if (l>r) return 0; 50 int m=(l+r)>>1; 51 key=cur; nth_element(a+l,a+m,a+r+1); 52 a[m].son[0]=build(l,m-1,cur^1); 53 a[m].son[1]=build(m+1,r,cur^1); 54 update(m); 55 return m; 56 } 57 void check(int q) 58 { 59 if (a[q].d[2]>po.d[2]) return; 60 ll l=dis(a[q],po); 61 if ((len>l)||((len==l)&&ans.id>a[q].id)) 62 { 63 ans=a[q]; 64 len=l; 65 } 66 } 67 ll get(int q) 68 { 69 if (!q||a[q].mi[2]>po.d[2]) return 1e18+5; 70 ll s=0; 71 for (int i=0; i<2; i++) 72 { 73 if (po.d[i]<a[q].mi[i]) s+=sqr(po.d[i]-a[q].mi[i]); 74 if (po.d[i]>a[q].mx[i]) s+=sqr(po.d[i]-a[q].mx[i]); 75 } 76 return s; 77 } 78 void ask(int q) 79 { 80 if (a[q].mi[2]>po.d[2]) return; 81 check(q); 82 int l=a[q].son[0],r=a[q].son[1]; 83 ll dl=get(l),dr=get(r); 84 if (dl<dr) 85 { 86 if (dl<=len) ask(l); 87 if (dr<=len) ask(r); 88 } 89 else { 90 if (dr<=len) ask(r); 91 if (dl<=len) ask(l); 92 } 93 } 94 } kd; 95 96 int main() 97 { 98 kd.init(); 99 int cas; 100 scanf("%d",&cas); 101 while (cas--) 102 { 103 scanf("%d%d",&n,&m); 104 for (int i=1; i<=n; i++) 105 { 106 int x,y,c; 107 scanf("%d%d%d",&x,&y,&c); 108 kd.a[i].d[0]=x; kd.a[i].d[1]=y; kd.a[i].d[2]=c; 109 kd.a[i].id=i; 110 } 111 root=kd.build(1,n,0); 112 for (int i=1; i<=m; i++) 113 { 114 scanf("%d%d%d",&po.d[0],&po.d[1],&po.d[2]); 115 len=1e18; kd.ask(root); 116 printf("%d %d %d\n",ans.d[0],ans.d[1],ans.d[2]); 117 } 118 } 119 }