欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

BZOJ 3053 The Closest M Points

程序员文章站 2022-04-03 09:00:29
...

 

【题目分析】

    典型的KD-Tree例题,求k维空间中的最近点对,只需要在判断的过程中加上一个优先队列,就可以了。

【代码】

    

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
 
#include <set>
#include <map>
#include <string>
#include <algorithm>
#include <vector>
#include <iostream>
#include <queue>
 
using namespace std;
 
#define maxn 1000005
#define inf (0x3f3f3f3f)
#define mk(a,b) make_pair(a,b)
 
int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
 
int D,rt,n,base,m,x;
 
struct node{
    int d[6],mx[6],mn[6],l,r;
    int operator [] (int x) {return d[x];}
    void init() {for (int i=0;i<base;++i) d[i]=read();}
}t[maxn],now;
 
bool operator < (node a,node b) {return a[D]<b[D];}
 
void update(int k)
{
    for (int i=0;i<base;++i)
    {
        t[k].mn[i]=min(t[k][i],min(t[t[k].l].mn[i],t[t[k].r].mn[i]));
        t[k].mx[i]=max(t[k][i],max(t[t[k].l].mx[i],t[t[k].r].mx[i]));
    }
}
 
int build(int l,int r,int dir)
{
    D=dir;
    int mid=(l+r)/2;
    nth_element(t+l,t+mid,t+r+1);
    for (int i=0;i<base;++i) t[mid].mn[i]=t[mid].mx[i]=t[mid][i];
    if (l<mid) t[mid].l=build(l,mid-1,(dir+1)%base); else t[mid].l=0;
    if (r>mid) t[mid].r=build(mid+1,r,(dir+1)%base); else t[mid].r=0;
    update(mid);
    return mid;
}
 
int dis(node a,node b)
{
    int ret=0;
    for (int i=0;i<base;++i)
        ret+=(a[i]-b[i])*(a[i]-b[i]);
    return ret;
}
 
pair <int,int> pa;
int ans[maxn];
priority_queue <pair<int,int> > q;
 
int getdis(int k)
{
    if (!k) return inf;
    int ret=0;
    for (int i=0;i<base;++i)
        if (now[i]<t[k].mn[i]) ret+=(t[k].mn[i]-now[i])*(t[k].mn[i]-now[i]);
    for (int i=0;i<base;++i)
        if (now[i]>t[k].mx[i]) ret+=(now[i]-t[k].mx[i])*(now[i]-t[k].mx[i]);
    return ret;
}
 
void query(int k)
{
    if (!k) return ;
    int dl=getdis(t[k].l),dr=getdis(t[k].r),d0=dis(t[k],now);
    if (d0<q.top().first) {q.pop(); q.push(mk(d0,k));}
    if (dl<dr)
    {
        if (dl<q.top().first) query(t[k].l);
        if (dr<q.top().first) query(t[k].r);
    }
    else
    {
        if (dr<q.top().first) query(t[k].r);
        if (dl<q.top().first) query(t[k].l);
    }
}
 
int main()
{
    while (scanf("%d%d",&n,&base)!=EOF)
    {
//      memset(t,0,sizeof t);
//      n=read(); base=read();
        for (int i=0;i<base;++i) t[0].mn[i]=inf,t[0].mx[i]=-inf;
        for (int i=1;i<=n;++i) t[i].init();
        rt=build(1,n,0);
        m=read();
        while (m--)
        {
            now.init(); x=read();
            for (int i=0;i<x;++i) q.push(mk(inf,0));
            query(rt);
            printf("the closest %d points are:\n",x);
            for (int i=x;i>=1;--i) ans[i]=q.top().second,q.pop();
            for (int i=1;i<=x;++i)
                for (int j=0;j<base;++j)
                    printf("%d%c",t[ans[i]][j],j==base-1?'\n':' ');
        }
    }
}