看了青岛赛区的题简单学了一下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 }
bzoj1941

 

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 }
hdu5992

 

posted on 2017-03-26 16:57  acphile  阅读(496)  评论(0编辑  收藏  举报