zoukankan      html  css  js  c++  java
  • 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的时候就会有问题,会去递归并不存在的子树从而出锅。其实先判断一下子树是否存在再做比较好,不容易出锅而且比较清晰。

  • 相关阅读:
    1024X768大图 (Wallpaper)
    (Mike Lynch)Application of linear weight neural networks to recognition of hand print characters
    瞬间模糊搜索1000万基本句型的语言算法
    单核与双核的竞争 INTEL P4 670对抗820
    FlashFTP工具的自动缓存服务器目录的功能
    LDAP over SSL (LDAPS) Certificate
    Restart the domain controller in Directory Services Restore Mode Remotely
    How do I install Active Directory on my Windows Server 2003 server?
    指针与指针变量(转)
    How to enable LDAP over SSL with a thirdparty certification authority
  • 原文地址:https://www.cnblogs.com/VisJiao/p/8485740.html
Copyright © 2011-2022 走看看