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);
          }
        }
      }
  • 相关阅读:
    关于SQL异地备份的方法(转)
    为VS2008添加OLE/COM 对象查看器
    Microsoft.SqlServer.Smo无法加载SqlServer.Management.Smo.Agent.JobBaseCollection解决方法(转)
    Python3+Pygame实现的射击游戏,很流畅,有音效
    Python项目第1集
    2021年Python3快速入门视频上线了,免费学!!!走起
    亲自动手实现Python+pygame中国象棋游戏
    人机对战版五子棋
    学生信息管理系统(Django入门级)
    Python3+pygame实现的flappy bird游戏,代码完整,还有音乐
  • 原文地址:https://www.cnblogs.com/zhujiangning/p/6196259.html
Copyright © 2011-2022 走看看