BZOJ2648&2716 kdtree

题意:初始给定一些点,两种操作: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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值