BZOJ2648&2716 kdtree

原创 2017年01月03日 15:44:10

题意:初始给定一些点,两种操作:1.询问一个点的最近点 2.加点
替罪羊kdtree即可,由于这题是我第一次写kdtree找最近点,查询写崩了,用读入优化卡时过的。。。
而且中途出现了很多问题:
1.树为空要返回0,要不就崩了
2.建树时记得更新size
3.初始50W个点,操作50W次,最多可能有100W个点
4.nth_element的比较函数我穿了个小于等于进去。。。无限RE

#include<cstdio>
#include<cmath>
#include<algorithm>
using std::nth_element;
inline int abs(int a)
{
    return a<0?-a:a;
}
struct pnt
{
    int p[2];
    pnt(int a=0,int b=0){p[0]=a,p[1]=b;}
    int& operator [](size_t x){return p[x];}
    const int& operator [](size_t x) const {return p[x];}
    inline bool operator == (const pnt &b) const{return p[0]==b[0]&&p[1]==b[1];}
    friend inline int __dis(const pnt &a,const pnt &b)
    {
        return abs(a[0]-b[0])+abs(a[1]-b[1]);
    }
};
inline bool cmp0(const pnt &a,const pnt &b)
{
    return a[0]<=b[0];
}
inline bool cmp1(const pnt &a,const pnt &b)
{
    return a[1]<=b[1];
}
bool(*cmp[2])(const pnt&,const pnt&)={cmp0,cmp1};
inline int __min(int a,int b){return a<b?a:b;}
inline void min(int &a,int b){if(b<a) a=b;}
inline void max(int &a,int b){if(a<b) a=b;}
inline void min(pnt &a,const pnt &b){min(a[0],b[0]),min(a[1],b[1]);}
inline void max(pnt &a,const pnt &b){max(a[0],b[0]),max(a[1],b[1]);}
struct node
{
    pnt v,mn,mx;
    node *l,*r;
    size_t sz;
    node(const pnt &v):v(v),mn(v),mx(v),l(0),r(0),sz(1){}
    inline void up()
    {
        if(l) min(mn,l->mn),max(mx,l->mx),sz+=l->sz;
        if(r) min(mn,r->mn),max(mx,r->mx),sz+=r->sz;
    }   
    inline void up(const pnt &p)
    {
        min(mn,p),max(mx,p);
    }
    inline int min_dis(const pnt &p)
    {
        if(!this) return 0x7fffffff;
        int x,y;
        if(cmp0(mn,p)&&cmp0(p,mx)) x=0;
        else x=__min(abs(p[0]-mn[0]),abs(mx[0]-p[0]));
        if(cmp1(mn,p)&&cmp1(p,mx)) y=0;
        else y=__min(abs(p[1]-mn[1]),abs(mx[1]-p[1]));
        return x+y;
    }
    inline void* operator new (size_t)
    {
        static unsigned char pool[1000000*sizeof(node)];
        static size_t k=-1;
        return (node*)pool+ ++k;
    }
    inline void reset()
    {
        mn=mx=v;
        sz=1;
    }
    int check(const pnt &p,bool k)
    {
        if(!this) return 0x7fffffff;
        int res=__dis(p,v);
        if(!res) return 0;
        bool way=cmp[k](v,p);
        min(res,(way?r:l)->check(p,!k));
        if((way?l:r)->min_dis(p)<res)
        min(res,(way?l:r)->check(p,!k));
        return res;
    }
}*ar[500000];
inline bool node_cmp0(node* a,node* b)
{
    return a->v[0]<b->v[0];
}
inline bool node_cmp1(node *a,node *b)
{
    return a->v[1]<b->v[1];
}
bool(*node_cmp[2])(node*,node*)={node_cmp0,node_cmp1};
int top;
const double A=0.7,B=log(1.0/0.7);
struct kdtree
{
    node *rt;
    bool bad;
    kdtree():rt(0),bad(0){}
    void tour(node *x)
    {
        if(!x) return;
        x->reset();
        tour(x->l);
        ar[++top]=x;
        tour(x->r);
    }
    void rebuild(node*& x,bool k,int l,int r)
    {
        if(r<l) {x=0;return;}
        int mid=l+r>>1;
        nth_element(ar+l,ar+mid,ar+r+1,node_cmp[k]);
        x=ar[mid];
        rebuild(x->l,!k,l,mid-1);
        rebuild(x->r,!k,mid+1,r);
        x->up();
    }
    inline void rebuild(node*& x,bool k)
    {
        top=-1;
        tour(x);
        rebuild(x,k,0,top);
    }
    inline int query(int x,int y)
    {
        return rt->check(pnt(x,y),0);
    }
    bool insert(node*& x,const pnt &p,bool k,size_t h)
    {
        if(!x)
        {
            x=new node(p);
            bad=h>log(rt->sz)/B;
            return 1;
        }
        if(x->v==p) return 0;
        if(cmp[k](p,x->v))
        {
            bool kre=insert(x->l,p,!k,h+1);
            x->sz+=kre;
            if(bad&&x->l->sz>x->sz*A) rebuild(x,k),bad=0;
            if(kre) x->up(p);
            return kre;
        }
        else
        {
            bool kre=insert(x->r,p,!k,h+1);
            x->sz+=kre;
            if(bad&&x->r->sz>x->sz*A) rebuild(x,k),bad=0;
            if(kre) x->up(p);
            return kre;
        }
    }
    inline void insert(int x,int y)
    {
        insert(rt,pnt(x,y),0,0);
    }
}tr;
int n,m,t,x,y;
const size_t str=1<<20;
struct Istream
{
    unsigned char buf[str],*s,*t;
    Istream():buf(),s(),t(){}
    inline unsigned char get()
    {
        if(s==t) t=buf+fread(s=buf,1,str-1,stdin);
        return *s++;
    }
    inline Istream& operator >> (int &x)
    {
        register unsigned char c;
        x=0;
        do c=get(); while(c<'0'||c>'9');
        while(c>='0'&&c<='9') x=x*10+c-'0',c=get();
        return *this;
    }
}cin;
struct Ostream
{
    unsigned char buf[str],*s,*t;
    Ostream():buf(),s(buf),t(buf+str-1){}
    ~Ostream(){fwrite(buf,1,s-buf,stdout);}
    inline void put(unsigned char c)
    {
        if(s==t) fwrite(s=buf,1,str-1,stdout);
        *s++=c;
    }
    inline Ostream& operator << (const int &x)
    {
        static int a[15],t;
        if(!x) return put('0'),put('\n'),*this;
        a[t=1]=x;
        while(a[t]) a[t+1]=a[t]/10,a[t++]%=10;
        while(--t) put(a[t]+'0');
        return put('\n'),*this;
    }
}cout;
int main()
{
    //freopen("angel.in","r",stdin);
    //freopen("angel.out","w",stdout);
    cin>>n>>m;
    for(int i=1;i<=n;++i)
    {
        cin>>x>>y;
        tr.insert(x,y);
    }
    for(int i=1;i<=m;++i)
    {
        cin>>t>>x>>y;
        if(t==1) tr.insert(x,y);
        else cout<<tr.query(x,y);
    }
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

【java】KDTree,实现个java版本,留着日后可能用得上

Java版本KDTree 在KDTree中,只有n >> 2 ^ xn时,在明显得有KDTCount n是点的个数, xn是点的维数 KDTCount是在KDTree搜索时计算距离的次数统计 p...
  • zhong123123123
  • zhong123123123
  • 2016年05月11日 19:56
  • 510

KDTree 解析 、构建

KDTree是每个节点都为k维点的二叉树。所有非叶子节点可以视作用一个超平面把空间分割成两部分。在超平面左边的点代表节点的左子树,在超平面右边的点代表节点的右子树。超平面的方向可以用(n mod k)...
  • zhuyingqingfen
  • zhuyingqingfen
  • 2014年05月15日 11:05
  • 2180

kdTree

什么是K近邻法 K近邻(k-nearest neighbor,k-NN)算法简单、直观:给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最近邻的k个实例,这k个实例的多数属于某个类,就把...
  • zm714981790
  • zm714981790
  • 2017年03月03日 16:28
  • 184

kdtree

kd树类似于geo hash,只不过是对点进行二分,用于范围查询和knn(k-nearest neighbors)查询。 实现如下: KDTree.java: import java.u...
  • jollyjumper
  • jollyjumper
  • 2016年01月26日 18:37
  • 1143

基于KDTree的KNN实现

KNN算法的KD树实现,涉及排序、top K等算法问题
  • u012328476
  • u012328476
  • 2016年09月20日 08:37
  • 745

谁是我邻居--kdTree&OcTree

由于分割工作需要对点云的邻近点进行操作,不断对比和访问某个点的邻居,所以决定点云的相邻关系是非常重要的。对于Scan来说,邻居关系是天然的。但对于很多杂乱点云,或者滤波,分割后的点云来说,邻居关系就已...
  • fandq1223
  • fandq1223
  • 2016年11月15日 19:59
  • 1391

KDtree简单版本

本文介绍一种用于高维空间中的快速最近邻和近似最近邻查找技术——Kd-Tree(Kd树)。Kd-Tree,即K-dimensional tree,是一种高维索引树形数据结构,常用于在大规模的高维数据空间...
  • u012772714
  • u012772714
  • 2016年09月02日 17:21
  • 511

HDU 2966 (kdtree板子题)

题目链接:点击这里题意:给出n个不同的点,求出离每个点欧几里得距离平方最近的其他点。只需要一点小技巧即可:当当前kdtree节点坐标和询问坐标一致时,距离改成无穷大(因为不能选择自己)。#includ...
  • morejarphone
  • morejarphone
  • 2016年11月19日 15:08
  • 587

PCL中的KDtree

k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构。主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索)。K-D树是二进制空间分割树的特殊的情况。 一个...
  • wi162yyxq
  • wi162yyxq
  • 2017年05月10日 09:44
  • 1011

kdtree c++版本

等我实现一个python版本的再贴上来 http://blog.csdn.net/zhl30041839/article/details/9277807 一、如何高效率地实现k近邻法? ...
  • haipengdai
  • haipengdai
  • 2016年07月19日 20:48
  • 1422
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:BZOJ2648&2716 kdtree
举报原因:
原因补充:

(最多只允许输入30个字)