zoukankan      html  css  js  c++  java
  • KD-tree(2维)

    用于动态插入以及求某点的最近点的距离(BZOJ2648,BZOJ2716)

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    
      int cnt,ans,n,m;
    
      struct data{
          int x,y;
      }point[500001]; 
      
      struct kd_node{
          int x,y,lc,rc,minx,miny,maxx,maxy;
      }tr[1000001];
    
      int dis(int x1,int y1,int x2,int y2){
          return(fabs(x1-x2)+fabs(y1-y2));
      }
    
      int mycomp1(const data&a,const data&b){
          return(a.y<b.y);
      }
      
      int mycomp2(const data&a,const data&b){
          return(a.x<b.x);
      }
    
      void kd_update(int po){
          if (tr[po].lc){
            tr[po].minx=min(tr[po].minx,tr[tr[po].lc].minx);    
            tr[po].miny=min(tr[po].miny,tr[tr[po].lc].miny);    
            tr[po].maxx=max(tr[po].maxx,tr[tr[po].lc].maxx);    
            tr[po].maxy=max(tr[po].maxy,tr[tr[po].lc].maxy);    
        };
        if (tr[po].rc){
            tr[po].minx=min(tr[po].minx,tr[tr[po].rc].minx);    
            tr[po].miny=min(tr[po].miny,tr[tr[po].rc].miny);    
            tr[po].maxx=max(tr[po].maxx,tr[tr[po].rc].maxx);    
            tr[po].maxy=max(tr[po].maxy,tr[tr[po].rc].maxy);    
        }
      }//维护包含子树中所有点的最小的矩形,左下角(minx,miny),右上角(maxx,maxy)
    
      void kd_build(int l,int r,int wd){
          if (wd) sort(point+l,point+r+1,mycomp1);else sort(point+l,point+r+1,mycomp2);//实际应选取方差最大的一维
          cnt++;
          int mid=(l+r)>>1,t=cnt;//mid实际应为与平均值最接近的
          tr[cnt].x=point[mid].x;tr[cnt].y=point[mid].y;
          tr[cnt].minx=point[mid].x;tr[cnt].maxx=point[mid].x;
          tr[cnt].miny=point[mid].y;tr[cnt].maxy=point[mid].y;
          if (l<mid){
            tr[t].lc=cnt+1;kd_build(l,mid-1,!wd);
        };
        if (mid<r){
          tr[t].rc=cnt+1;kd_build(mid+1,r,!wd);
        }
        kd_update(t);
      }//构建n点的KD树,每次以一维为标准划分点
      
      void kd_ins(int po,int x,int y,int d){
          int son=0;
          if (d==0) son=(x<=tr[po].x);else son=(y<=tr[po].y);
          if (son==1){
            if (tr[po].lc==0){
                tr[po].lc=++cnt;
                tr[cnt].x=x;tr[cnt].y=y;
                tr[cnt].minx=x;tr[cnt].maxx=x;
            tr[cnt].miny=y;tr[cnt].maxy=y;
          }else kd_ins(tr[po].lc,x,y,!d);
        }else{
          if (tr[po].rc==0){
              tr[po].rc=++cnt;
              tr[cnt].x=x;tr[cnt].y=y;
                tr[cnt].minx=x;tr[cnt].maxx=x;
            tr[cnt].miny=y;tr[cnt].maxy=y;
          }else kd_ins(tr[po].rc,x,y,!d);
        }
        kd_update(po);
      } 
      
      int dist(int x,int y,int po){
          int ret=0;
          ret+=max(0,tr[po].minx-x);
          ret+=max(0,x-tr[po].maxx);
          ret+=max(0,tr[po].miny-y);
        ret+=max(0,y-tr[po].maxy);
        return(ret);
      }//(x,y)到po子树维护的矩形的最近距离。假设该矩形中铺满点,所以返回值小于等于实际值
      
      void kd_query(int po,int x,int y){
          ans=min(ans,dis(x,y,tr[po].x,tr[po].y));
          int dl=(tr[po].lc==0 ? 1e9:dist(x,y,tr[po].lc));
          int dr=(tr[po].rc==0 ? 1e9:dist(x,y,tr[po].rc));
          if (dl<dr){
            if (dl<ans) kd_query(tr[po].lc,x,y);
          if (dr<ans) kd_query(tr[po].rc,x,y);    
        }else{
          if (dr<ans) kd_query(tr[po].rc,x,y);
          if (dl<ans) kd_query(tr[po].lc,x,y);
        }
      }//以dist为估价函数搜寻
    
      int main(){
          scanf("%d%d",&n,&m);
          for (int i=1;i<=n;i++) scanf("%d%d",&point[i].x,&point[i].y);
          kd_build(1,n,0);
          
          for (int i=1;i<=m;i++){
            int opt,x,y;
            scanf("%d%d%d",&opt,&x,&y);
          
          if (opt==1){
              kd_ins(1,x,y,0);
          }else{
              ans=1e9;
              kd_query(1,x,y);
              printf("%d
    ",ans);
          }
        }
      }

     ____________________________________________

    BZOJ4066

    单点修改,矩形求和

    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
      int cnt,tcnt,n;
    
      struct data{
          int x,y,v;
      }a[200001];
    
      struct treenode{
          int lc,rc,x,y,minx,miny,maxx,maxy,num,v;
      }tr[200001];
    
      void update(int po){
          tr[po].num=tr[tr[po].lc].num+tr[tr[po].rc].num+tr[po].v;
          tr[po].minx=min(min(tr[tr[po].lc].minx,tr[tr[po].rc].minx),tr[po].x);
          tr[po].miny=min(min(tr[tr[po].lc].miny,tr[tr[po].rc].miny),tr[po].y);
          tr[po].maxx=max(max(tr[tr[po].lc].maxx,tr[tr[po].rc].maxx),tr[po].x);
          tr[po].maxy=max(max(tr[tr[po].lc].maxy,tr[tr[po].rc].maxy),tr[po].y);
      }
    
      void insert(int po,int x,int y,int num,int wd){
          if (tr[po].x==x&&tr[po].y==y){
            tr[po].num+=num;tr[po].v+=num;return;    
        }
        
        int sel;
        if (!wd) sel=(tr[po].x<x);else sel=(tr[po].y<y);
        if (!sel){
          if (!tr[po].lc){
              cnt++;
              tr[cnt].x=tr[cnt].minx=tr[cnt].maxx=x;
            tr[cnt].y=tr[cnt].miny=tr[cnt].maxy=y;
            tr[cnt].v=tr[cnt].num=num;
            tr[po].lc=cnt;
            update(po);
          }else insert(tr[po].lc,x,y,num,!wd);    
        }else{
          if (!tr[po].rc){
              cnt++;
              tr[cnt].x=tr[cnt].minx=tr[cnt].maxx=x;
            tr[cnt].y=tr[cnt].miny=tr[cnt].maxy=y;
            tr[cnt].v=tr[cnt].num=num;
            tr[po].rc=cnt;
            update(po);
           }else insert(tr[po].rc,x,y,num,!wd);    
        }
        update(po);
      }
      
      int mycomp1(const data&a,const data&b){
          return(a.x<b.x);
      }
      
      int mycomp2(const data&a,const data&b){
          return(a.y<b.y);
      }
      
      void build(int l,int r,int wd){
          if (wd==0) sort(a+l,a+r+1,mycomp1);else sort(a+l,a+r+1,mycomp2);
          int mid=(l+r)>>1;
          int tmp=++tcnt;
         tr[tcnt].lc=tr[tcnt].rc=0;
          tr[tcnt].x=a[mid].x;tr[tcnt].y=a[mid].y;tr[tcnt].v=a[mid].v;
          if (l<mid){
            tr[tmp].lc=tcnt+1;build(l,mid-1,!wd);    
        };
        if (r>mid){
          tr[tmp].rc=tcnt+1;build(mid+1,r,!wd);
        }
        update(tmp);
      }
      
      int in(int x1,int y1,int x2,int y2,int X1,int Y1,int X2,int Y2){
          return(X1<=x1&&Y1<=y1&&X2>=x2&&Y2>=y2);
      }
      
      int out(int x1,int y1,int x2,int y2,int X1,int Y1,int X2,int Y2){
        return(x2<X1||x1>X2||y1>Y2||y2<Y1);
      }
      
      int query(int po,int x1,int y1,int x2,int y2){
          int ret=0;
          if (in(tr[po].minx,tr[po].miny,tr[po].maxx,tr[po].maxy,x1,y1,x2,y2)) return(tr[po].num);
          
          if (in(tr[po].x,tr[po].y,tr[po].x,tr[po].y,x1,y1,x2,y2)) ret+=tr[po].v;
          if (!out(tr[tr[po].lc].minx,tr[tr[po].lc].miny,tr[tr[po].lc].maxx,tr[tr[po].lc].maxy,x1,y1,x2,y2)) ret+=query(tr[po].lc,x1,y1,x2,y2);
          if (!out(tr[tr[po].rc].minx,tr[tr[po].rc].miny,tr[tr[po].rc].maxx,tr[tr[po].rc].maxy,x1,y1,x2,y2)) ret+=query(tr[po].rc,x1,y1,x2,y2);
          return(ret);
      }
      
      int main(){
          scanf("%d",&n);
          tr[0].miny=tr[0].minx=1e9;
          tr[0].maxx=tr[0].maxy=-1e9;
          int opt,lastans=0,lastrebuild=0,root=0;
          while (scanf("%d",&opt),opt!=3){
            int x,y,x1,y1,x2,y2,num;    
              
          if (opt==1){
              scanf("%d%d%d",&x,&y,&num);
                x^=lastans;y^=lastans;num^=lastans;
              if (!root){
                root=1;
                cnt++;
                tr[cnt].x=tr[cnt].minx=tr[cnt].maxx=x;
              tr[cnt].y=tr[cnt].miny=tr[cnt].maxy=y;
              tr[cnt].v=tr[cnt].num=num;
            }else{
              insert(root,x,y,num,0);
            }
            
            if (cnt/10000>lastrebuild){
              for (int i=1;i<=cnt;i++) a[i].x=tr[i].x,a[i].y=tr[i].y,a[i].v=tr[i].v;
              tcnt=0;
              build(1,cnt,0);     
              lastrebuild++;
            }
          }
          
          if (opt==2){
              scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                x1^=lastans;x2^=lastans;y1^=lastans;y2^=lastans;
              lastans=query(1,x1,y1,x2,y2);
              printf("%d
    ",lastans);
          }
        }
      }
  • 相关阅读:
    python 的基础 学习 第六天 基础数据类型的操作方法 字典
    python 的基础 学习 第五天 基础数据类型的操作方法
    python 的基础 学习 第四天 基础数据类型
    ASP.NET MVC 入门8、ModelState与数据验证
    ASP.NET MVC 入门7、Hellper与数据的提交与绑定
    ASP.NET MVC 入门6、TempData
    ASP.NET MVC 入门5、View与ViewData
    ASP.NET MVC 入门4、Controller与Action
    ASP.NET MVC 入门3、Routing
    ASP.NET MVC 入门2、项目的目录结构与核心的DLL
  • 原文地址:https://www.cnblogs.com/zhujiangning/p/6196259.html
Copyright © 2011-2022 走看看