zoukankan      html  css  js  c++  java
  • bzoj1941 hdu5992

    看了青岛赛区的题简单学了一下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
    ",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
    ",ans.d[0],ans.d[1],ans.d[2]);
    117         }
    118     }
    119 }
    hdu5992
  • 相关阅读:
    centos 系统查看raid信息
    021-制作OpenStack镜像官方文档
    020-VMware虚拟机作为OpenStack计算节点,上面的虚拟机无法启动问题解决
    019-openstack组件使用的默认端口号
    CentOS7搭建FastDFS+Nginx
    zabbix 安装中文无法显示的问题
    ##6.2 Neutron计算节点-- openstack pike
    thinkphp 5.6以上版本出现No input file specified解决办法
    单/多行——超出文字变成.....
    修改cmd为utf-8编码:
  • 原文地址:https://www.cnblogs.com/phile/p/6623285.html
Copyright © 2011-2022 走看看