zoukankan      html  css  js  c++  java
  • BZOJ3053

    原题链接

    Description

    给出K(K5)维空间中的n(n5×104)个点,然后t(t104)次询问距离某个坐标m(m10)近的点,将这m个点由近到远输出。坐标的绝对值不超过104

    Solution

    跟普通的k-d树差不多,就是要开一个容量为m的大根堆,初始堆里有minf,比较时如果比堆顶小就插入,如果到区间的距离都比堆顶要大就不需要做了。

    Code

    这个代码目前RE!又是对拍全过然后GG…

    //The Closest M Points
    #include <cstdio>
    #include <algorithm>
    #include <queue>
    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,f=1; char ch=gc();
        while((ch<'0'||'9'<ch)&&ch!=EOF) {if(ch=='-') f=-1; ch=gc();}
        while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
        return x*f;
    }
    int const N=5e4+10;
    int const INF=0x7FFFFFFF;
    int n,K;
    #define ch1 ch[p][0]
    #define ch2 ch[p][1]
    int rt,ch[N][2];
    struct point{int c[5];} pt[N];
    struct zone{int c1[5],c2[5];} zn[N];
    int D; bool cmpPt(point x,point y) {return x.c[D]<y.c[D];}
    void update(int p)
    {
        for(int k=0;k<K;k++)
        {
            zn[p].c1[k]=min(pt[p].c[k],min(zn[ch1].c1[k],zn[ch2].c1[k]));
            zn[p].c2[k]=max(pt[p].c[k],max(zn[ch1].c2[k],zn[ch2].c2[k]));
        }
    }
    void build(int &p,int L,int R,int k0)
    {
        p=L+R>>1; D=k0;
        nth_element(pt+L,pt+p,pt+R+1,cmpPt);
        if(L<p) build(ch[p][0],L,p-1,(k0+1)%K);
        if(p<R) build(ch[p][1],p+1,R,(k0+1)%K);
        update(p);
    }
    point A;
    int dst(point B)
    {
        int res=0; if(B.c[0]==INF) return INF;
        for(int k=0;k<K;k++) res+=(A.c[k]-B.c[k])*(A.c[k]-B.c[k]);
        return res;
    }
    int dst(zone z)
    {
        int res=0;
        for(int k=0;k<K;k++)
            if(A.c[k]<z.c1[k]) res+=(z.c1[k]-A.c[k])*(z.c1[k]-A.c[k]);
            else if(z.c2[k]<A.c[k]) res+=(A.c[k]-z.c2[k])*(A.c[k]-z.c2[k]);
        return res;
    }
    #define pInt pair<int,int>
    priority_queue< pInt,vector<pInt>,less<pInt> > q;
    void query(int p)
    {
        if(dst(pt[p])<dst(pt[q.top().second])) q.pop(),q.push(make_pair(dst(pt[p]),p));
        int p0=q.top().second;
        if(ch1&&dst(zn[ch1])<dst(pt[p0])) query(ch1);
        if(ch2&&dst(zn[ch2])<dst(pt[p0])) query(ch2);
    }
    int ans[20];
    int main()
    {
        while(true)
        {
    
        n=read(),K=read(); if(n==0) break;
        for(int k=0;k<K;k++) pt[0].c[k]=INF,zn[0].c1[k]=INF,zn[0].c2[k]=-INF;
        for(int i=1;i<=n;i++)
            for(int k=0;k<K;k++) pt[i].c[k]=read();
        build(rt,1,n,0);
        int t=read();
        while(t--)
        {
            for(int k=0;k<K;k++) A.c[k]=read();
            int m=read(); for(int i=1;i<=m;i++) q.push(make_pair(INF,0));
            query(rt);
            printf("the closest %d points are:
    ",m);
            for(int i=m;i>=1;i--) ans[i]=q.top().second,q.pop();
            for(int i=1;i<=m;i++)
            {
                for(int k=0;k<K;k++) printf("%d ",pt[ans[i]].c[k]);
                printf("
    ");
            }
            while(!q.empty()) q.pop();
        }
    
        }
        return 0;
    }

    P.S.

    我好菜啊…

  • 相关阅读:
    NET开发中的事务处理大比拼
    gridview 导出Excel
    项目 心得
    设计模式Prototype原型模式
    设计模式Memento 备忘录模式
    设计模式Chain Of Responsibility 职责链模式
    设计模式Composite组合模式
    .NET常用功能和代码[总结与收藏]
    SQL SERVER函数——表值函数的处理
    设计模式学习笔记 简单工厂模式
  • 原文地址:https://www.cnblogs.com/VisJiao/p/8485745.html
Copyright © 2011-2022 走看看