zoukankan      html  css  js  c++  java
  • BZOJ 2648 SJY摆棋子(KD树)

    【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=2716

    【题目大意】

      给出一些点,同时不断插入点和询问某点离插入点最近距离

    【题解】

      我们对于给定的点直接建树,之后动态插入查询即可,重建会超时,
      直接插入就可以过了

    【代码】

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N=1500000,INF=1e9;
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    namespace KD_Tree{
        struct Dot{  
            int d[2],mn[2],mx[2],l,r,sz;  
            Dot(){l=r=0;}  
            Dot(int x,int y){d[0]=x;d[1]=y;l=r=sz=0;}  
            int& operator [] (int x){return d[x];}  
        };  
        int D,pt[N],dcnt=0; 
        Dot T[N],p[N];
        bool operator<(Dot a,Dot b){return a[D]<b[D];}
        inline void umax(int&a,int b){if(a<b)a=b;}
        inline void umin(int&a,int b){if(a>b)a=b;}
        inline bool cmp(int x,int y){return T[x][D]<T[y][D];}
        inline void up(int x){
            T[x].sz=T[T[x].l].sz+T[T[x].r].sz+1;
            T[x].mn[0]=T[x].mx[0]=T[x][0];  
            T[x].mn[1]=T[x].mx[1]=T[x][1]; 
            if(T[x].l){
                umax(T[x].mx[0],T[T[x].l].mx[0]);
                umin(T[x].mn[0],T[T[x].l].mn[0]);   
                umax(T[x].mx[1],T[T[x].l].mx[1]);
                umin(T[x].mn[1],T[T[x].l].mn[1]);
            }
            if(T[x].r){
                umax(T[x].mx[0],T[T[x].r].mx[0]);
                umin(T[x].mn[0],T[T[x].r].mn[0]);
                umax(T[x].mx[1],T[T[x].r].mx[1]);
                umin(T[x].mn[1],T[T[x].r].mn[1]);
            }
        }
        inline int NewDot(int x,int y){
            ++dcnt; pt[dcnt]=dcnt;
            T[dcnt][0]=x; T[dcnt][1]=y;
            return up(dcnt),dcnt;
        }
        void AddDot(int x,int y){
            ++dcnt; pt[dcnt]=dcnt;
            p[dcnt][0]=x; p[dcnt][1]=y;
        }
        // 曼哈顿距离估价函数
        inline int dist(int p1,int px,int py){
            int dis=0;
            if(px<T[p1].mn[0])dis+=T[p1].mn[0]-px;
            if(px>T[p1].mx[0])dis+=px-T[p1].mx[0];
            if(py<T[p1].mn[1])dis+=T[p1].mn[1]-py;
            if(py>T[p1].mx[1])dis+=py-T[p1].mx[1];
            return dis;
        }
        //查询(px,py)最近点距离
        int ans=0;
        inline void ask(int x,int px,int py){
            int dl,dr,d0=abs(T[x][0]-px)+abs(T[x][1]-py);
            if(d0<ans)ans=d0;
            dl=T[x].l?dist(T[x].l,px,py):INF;
            dr=T[x].r?dist(T[x].r,px,py):INF;
            if(dl<dr){
                if(dl<ans)ask(T[x].l,px,py);
                if(dr<ans)ask(T[x].r,px,py);
            }else{
                if(dr<ans)ask(T[x].r,px,py);
                if(dl<ans)ask(T[x].l,px,py);
            }
        }
        int query(int x,int px,int py){
            ans=INF; ask(x,px,py);
            return ans;
        }
        void Insert(int&x,int D,const Dot&p){  
            if(!x){x=NewDot(p.d[0],p.d[1]);return;}  
            if(p.d[D]<T[x][D])Insert(T[x].l,D^1,p);  
            else Insert(T[x].r,D^1,p);  
            up(x);  
        }
        // 建树 
        int build(int l,int r,int now){
            int mid=(l+r)>>1;
            D=now;
            nth_element(p+l,p+mid,p+r+1);
            T[mid]=p[mid];
            for(int i=0;i<2;i++)T[mid].mn[i]=T[mid].mx[i]=T[mid][i];
            if(l<mid)T[mid].l=build(l,mid-1,now^1);
            if(r>mid)T[mid].r=build(mid+1,r,now^1);
            return up(mid),mid;
        }
        // 暴力重构
        int Rebuild(int l,int r,int now){  
            if(l>r)return 0;  
            int mid=(l+r)>>1,x;  
            D=now;  
            nth_element(pt+l,pt+mid,pt+r+1,cmp);  
            x=pt[mid];  
            T[x].l=Rebuild(l,mid-1,now^1);  
            T[x].r=Rebuild(mid+1,r,now^1);  
            return up(x),x;  
        } 
    }
    int n,m,x,y,root=0,c;
    int main(){
        n=read(); m=read();
        for(int i=1;i<=n;i++)KD_Tree::AddDot(read(),read());
        root=KD_Tree::build(1,KD_Tree::dcnt,0);
        while(m--){
            if(read()==1)KD_Tree::Insert(root,0,KD_Tree::Dot(read(),read()));
            else printf("%d
    ",KD_Tree::query(root,read(),read()));
            // if(KD_Tree::dcnt%5000==0)root=KD_Tree::Rebuild(1,KD_Tree::dcnt,0); 
            // 重构会超时,不重构能过 
        }return 0;
    }
  • 相关阅读:
    网络测量中基于Sketch方法的简单介绍
    Reading SBAR SDN flow-Based monitoring and Application Recognition
    Reading Meticulous Measurement of Control Packets in SDN
    Reading SketchVisor Robust Network Measurement for Sofeware Packet Processing
    ovs加dpdk在日志中查看更多运行细节的方法
    后缀数组
    (转载)LCA问题的Tarjan算法
    Codeforces Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) A. Checking the Calendar(水题)
    Vijos 1816统计数字(计数排序)
    卡特兰数
  • 原文地址:https://www.cnblogs.com/forever97/p/bzoj2648.html
Copyright © 2011-2022 走看看