• HDU5992


    原题链接

    Description

    给出n(n2×105)个二维平面上的点,每个点有权值cm(m2×104)次询问,求所有权值小于等于c的点中,距离坐标(x,y)的欧几里得距离最小的点。如果有多个满足条件的点,输出最靠前的一个。

    Solution

    拿k-d树搞一搞就好啦。
    如果一个子树代表的区域中所有点的权值都大于c,或者到所有点的距离都大于当前答案,就跳过不做。

    Code

    //Finding Hotels
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    inline char gc()
    {
        static char now[1<<16],*S,*T;
        if(S==T) {T=(S=now)+fread(now,1,1<<16,stdin); if(S==T) return EOF;}
        return *S++;
    }
    inline int read()
    {
        int x=0; char ch=gc();
        while(ch<'0'||'9'<ch) ch=gc();
        while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
        return x;
    }
    typedef long long lint;
    int const N=2e5+10;
    lint const INF=1LL<<62;
    int n,m;
    int rt,ch[N][2];
    struct point{lint c[3]; int id;} pt[N];
    struct zone{lint c1[3],c2[3];} zn[N];
    int D; bool cmpPt(point x,point y) {return x.c[D]<y.c[D];}
    void create(int p)
    {
        for(int k=0;k<3;k++) zn[p].c1[k]=zn[p].c2[k]=pt[p].c[k];
        ch[p][0]=ch[p][1]=0;
    }
    void update(int p)
    {
        for(int k=0;k<3;k++)
            zn[p].c1[k]=min(pt[p].c[k],min(zn[ch[p][0]].c1[k],zn[ch[p][1]].c1[k])),
            zn[p].c2[k]=max(pt[p].c[k],max(zn[ch[p][0]].c2[k],zn[ch[p][1]].c2[k]));
    }
    void build(int &p,int L,int R,int k0)
    {
        p=L+R>>1; create(p);
        if(k0==3) k0=0; D=k0;
        nth_element(pt+L,pt+p,pt+R+1,cmpPt);
        if(L<p) build(ch[p][0],L,p-1,k0+1);
        if(p<R) build(ch[p][1],p+1,R,k0+1);
        update(p);
    }
    point A; int r; lint rDst;
    lint dst(point B)
    {
        if(B.c[2]>A.c[2]) return INF;
        return (A.c[0]-B.c[0])*(A.c[0]-B.c[0])+(A.c[1]-B.c[1])*(A.c[1]-B.c[1]);
    }
    lint dst(zone z)
    {
        if(z.c1[0]==INF||z.c1[2]>A.c[2]) return INF+1;
        lint sum=0;
        for(int k=0;k<2;k++)
        {
            lint d=0;
            if(A.c[k]<z.c1[k]) d=z.c1[k]-A.c[k];
            else if(z.c2[k]<A.c[k]) d=A.c[k]-z.c2[k];
            sum+=d*d;
        }
        return sum;
    }
    void query(int p)
    {
        lint d=dst(pt[p]);
        if(d<rDst||(d==rDst&&pt[p].id<pt[r].id)) r=p,rDst=d;
        if(dst(zn[ch[p][0]])<=rDst) query(ch[p][0]);
        if(dst(zn[ch[p][1]])<=rDst) query(ch[p][1]);
    }
    int main()
    {
        int task=read();
        for(int k=0;k<3;k++) zn[0].c1[k]=INF,zn[0].c2[k]=-INF;
        while(task--)
        {
    
        n=read(),m=read();
        memset(pt,0,sizeof pt);
        for(int i=1;i<=n;i++)
            for(int k=0;k<3;k++) pt[i].c[k]=read();
        for(int i=1;i<=n;i++) pt[i].id=i;
        rt=0; build(rt,1,n,0);
        for(int i=1;i<=m;i++)
        {
            for(int k=0;k<3;k++) A.c[k]=read();
            r=0,rDst=INF,query(rt);
            printf("%lld %lld %lld
    ",pt[r].c[0],pt[r].c[1],pt[r].c[2]);
        }
    
        }
        return 0;
    }

    P.S.

    要开long long哦。
    55行在不合法时返回INF+1,是因为我懒得判断左右子树是否存在而这么写的。由于要求最靠前的点,所以dst()==rDst的时候也要做,但如果dst()由于不合法而返回INF的话,在rDst==INF的时候就会有问题,会去递归并不存在的子树从而出锅。其实先判断一下子树是否存在再做比较好,不容易出锅而且比较清晰。

  • 相关阅读:
    python—Celery异步分布式
    python 安装虚拟环境步骤
    同源策略:
    git 的用法和命令
    一分钟搞定AlloyTouch图片轮播
    JavaScript学习总结(一)——延迟对象、跨域、模板引擎、弹出层、AJAX示例
    CSS3与页面布局学习总结(八)——浏览器兼容与前端性能优化
    移动前端UI选择
    你必须收藏的Github技巧
    HTML5 学习笔记(二)——HTML5新增属性与表单元素
  • 原文地址:https://www.cnblogs.com/VisJiao/p/8485740.html
Copyright © 2020-2023  润新知