zoukankan      html  css  js  c++  java
  • [hdu4347]The Closest M Points(平衡树式kdtree)

    解题关键:模板题(结合起来了)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    #include<cstdlib>
    #define N 50050
    #define inf (1<<30)
    #define sq(x) (x)*(x)
    using namespace std;
    int n,m,dim,rt,k;
    struct node{
        int p[10],minn[10],maxx[10];
        bool operator<(const node &u)const{
            return p[dim]<u.p[dim];
        }
    }a[N];
    typedef pair<double,node>PDN;
    priority_queue<PDN>que;
    struct kd_tree{
        int c[N][2];
        node s[N],q;
        void update(int o){//管辖范围
            int l=c[o][0],r=c[o][1];
            for(int i=0;i<k;i++){
                if(l){ s[o].minn[i]=min(s[o].minn[i],s[l].minn[i]); s[o].maxx[i]=max(s[o].maxx[i],s[l].maxx[i]); }
                if(r){ s[o].minn[i]=min(s[o].minn[i],s[r].minn[i]); s[o].maxx[i]=max(s[o].maxx[i],s[r].maxx[i]); }
            }
        }
        void add(int o,node t){ for(int i=0;i<k;i++)s[o].minn[i]=s[o].maxx[i]=s[o].p[i]=t.p[i]; c[o][0]=c[o][1]=0;}
        int dist(node t,int o){
            int tmp=0;
            for(int i=0;i<k;i++){
                if(s[o].minn[i]>t.p[i])tmp+=sq(s[o].minn[i]-t.p[i]);
                if(t.p[i]>s[o].maxx[i])tmp+=sq(t.p[i]-s[o].maxx[i]);
            }
            return tmp;
        }
        void build(int &o,int l,int r,int now){
            o=(l+r)>>1;now%=k;dim=now;
            nth_element(a+l,a+o,a+r+1);
            add(o,a[o]);
            if(l!=o) build(c[o][0],l,o-1,now+1);
            if(o!=r) build(c[o][1],o+1,r,now+1);
            update(o);
        }
        void ins(int o,int now){
            now%=k;
            if(q.p[now]<s[o].p[now]){
                if(c[o][0]) ins(c[o][0],now+1);
                else c[o][0]=++n,add(n,q);
            }
            else{
                if(c[o][1]) ins(c[o][1],now+1);
                else c[o][1]=++n,add(n,q);
            }
            update(o);
        }
        void qry(int o){//曼哈顿距离,且只求最短,dis是最短距离
            PDN tmp=PDN(0,s[o]);
            for(int i=0;i<k;i++) tmp.first+=sq(s[o].p[i]-q.p[i]);
            if(que.size()<m) que.push(tmp);
            else{
                if(que.top().first>tmp.first){
                    que.pop();
                    que.push(tmp);
                }
            }
            int dl=c[o][0]?dist(q,c[o][0]):inf,dr=c[o][1]?dist(q,c[o][1]):inf;
            if(dl<dr){
                if((dl<que.top().first||que.size()<m)&&dl!=inf) qry(c[o][0]);
                if((dr<que.top().first||que.size()<m)&&dr!=inf) qry(c[o][1]);
            }else{
                if((dr<que.top().first||que.size()<m)&&dr!=inf) qry(c[o][1]);
                if((dl<que.top().first||que.size()<m)&&dl!=inf) qry(c[o][0]);
            }
        }
    }kd;
    
    int main(){
        while(scanf("%d%d",&n,&k)!=EOF){
            for(int i=1;i<=n;i++){
                for(int j=0;j<k;j++)
                    scanf("%d",&a[i].p[j]);
            }
            kd.build(rt,1,n,0);
            int t;
            scanf("%d",&t);
            while(t--){
                while(!que.empty()) que.pop();
                for(int j=0;j<k;j++) scanf("%d",&kd.q.p[j]);
                scanf("%d",&m);
                kd.qry(rt);
                node pp[100];
                int nn=0;
                printf("the closest %d points are:
    ",m);
                while(!que.empty()) pp[++nn]=que.top().second,que.pop();
                for(int i=m;i>0;i--){
                    for(int j=0;j<k;j++){
                        printf("%d%c",pp[i].p[j],j==k-1?'
    ':' ');
                    }
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    如何开始DDD(续)
    如何开始DDD
    ThinkNet终于见面了
    [Umbraco] umbraco中如何分页
    ETL 工具下载全集 包括 Informatica Datastage Cognos( 持续更新)
    js时间对比-转化为几天前,几小时前,几分钟前
    原生JS实现返回顶部和滚动锚点
    JSONP原理及简单实现 可做简单插件使用
    CSS3 transition效果 360度旋转 旋转放大 放大 移动
    js获取url的常用方法
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/10493541.html
Copyright © 2011-2022 走看看