zoukankan      html  css  js  c++  java
  • bzoj 2716 [Violet 3]天使玩偶——KDtree

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2716

    第三道KDtree!仍旧是模板。还有CDQ分治做法,见下面。

    数组迷之开大?(开6e5+5还不行)

    原来query( )只用传一个根。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=3e6+5,INF=0x3f3f3f3f;
    int n,m,ans,rt,tot;
    bool fx;
    struct Dt{
        int x[2],y[2],p[2];
    }a[N>>1];
    bool cmp(Dt u,Dt v){return u.p[fx]<v.p[fx];}
    struct KD{
        int c[N][2]; Dt s[N],q;
        void add(int cr,Dt k)
        {    for(int i=0;i<=1;i++) s[cr].x[i]=s[cr].y[i]=s[cr].p[i]=k.p[i];}
        void pshp(int cr)
        {
            int ls=c[cr][0],rs=c[cr][1];
            for(int i=0;i<=1;i++)
            {
                if(ls) s[cr].x[i]=min(s[cr].x[i],s[ls].x[i]),
                       s[cr].y[i]=max(s[cr].y[i],s[ls].y[i]);
                if(rs) s[cr].x[i]=min(s[cr].x[i],s[rs].x[i]),
                       s[cr].y[i]=max(s[cr].y[i],s[rs].y[i]);
            }
        }
        void build(int &cr,int l,int r,bool now)
        {
            int mid=l+r>>1; fx=now; nth_element(a+l,a+mid,a+r+1,cmp);
            cr=++tot;  add(cr,a[mid]);
            if(l<mid) build(c[cr][0],l,mid-1,!now);
            if(mid<r) build(c[cr][1],mid+1,r,!now);
            pshp(cr);
        }
        void insert(int &cr,bool now)
        {
            if(!cr){cr=++tot; add(cr,q); return;}
            if(q.p[now]<s[cr].p[now]) insert(c[cr][0],!now);
            else insert(c[cr][1],!now);
            pshp(cr);
        }
        int dis(int cr,Dt k){return abs(s[cr].p[0]-k.p[0])+abs(s[cr].p[1]-k.p[1]);}
        int dist(int cr,Dt k)
        {
            int ret=0;
            for(int i=0;i<=1;i++)
                ret+=max(0,s[cr].x[i]-k.p[i])+max(0,k.p[i]-s[cr].y[i]);
            return ret;
        }
        void query(int cr)
        {
            ans=min(ans,dis(cr,q));
            int ls=c[cr][0],rs=c[cr][1];
            int dl=(ls?dist(ls,q):INF),dr=(rs?dist(rs,q):INF);
            if(dl<dr) {if(dl<ans) query(ls); if(dr<ans) query(rs);}
            else {if(dr<ans) query(rs); if(dl<ans) query(ls);}
        }
    }kd;
    int rdn()
    {
        int ret=0;char ch=getchar();
        while(ch>'9'||ch<'0') ch=getchar();
        while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0', ch=getchar();
        return ret;
    }
    int main()
    {
        n=rdn(); m=rdn();
        for(int i=1;i<=n;i++) a[i].p[0]=rdn(), a[i].p[1]=rdn();
        kd.build(rt,1,n,0);
        for(int i=1,op;i<=m;i++)
        {
            op=rdn();kd.q.p[0]=rdn();kd.q.p[1]=rdn();
            if(op==1) kd.insert(rt,0);
            else { ans=INF;  kd.query(rt);  printf("%d
    ",ans);}
        }
        return 0;
    }

     CDQ分治做法可看看这个人的博客:https://www.cnblogs.com/longshengblog/p/5511593.html

      大约就是算距离的时候用 (x+y)-(x'+y') ,(x'<x,y'<=y) 。但只是这样只能算左下角的;所以用maxx-x作为新的x,y还是原来的,就能算右下角;用maxy-y作为新的y,x还是原来的,就能算左上角;x和y都减了,就能算右上角。那个博客的实现很简洁,所以自己就懒得写了(?)。

  • 相关阅读:
    mysql perl 抓取update语句
    $/ 改变换行符
    $/ 改变换行符
    java读取jpg图片旋转按比例缩放
    感应器
    lisp分支
    鸡肋的Drools
    postgre去重复记录
    拖拽到指定位置
    base64coder调用
  • 原文地址:https://www.cnblogs.com/Narh/p/9599533.html
Copyright © 2011-2022 走看看