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;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

【BZOJ】【P2648&P2716】【SJY摆棋子】【天使玩偶】【题解】【kdtree】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2648 http://www.lydsy.com/JudgeOnline/problem.ph...

BZOJ 2716 [Violet 3]天使玩偶 KDtree

以下引用自“‎Alboi_真神名曰驴蛋蛋”对于一颗普通的K-D树,让K-D树上每个节点记录它这颗子树的大小(size)和这颗子树所能延伸到的最大横坐标,最小横坐标,最大纵坐标,最小纵坐标......就...

KDtree(bzoj2648)

我的第一篇博客

BZOJ 2648 SJY摆棋子 / 2716 Violet 3 天使玩偶 K-D树

题目大意:平面上有一些点,问一个点周围离它最近的点的曼哈顿距离是多少。支持动态加点。 思路:CDQ分治可以离线解决,但是SJY是卡CDQ的,天使玩偶可以过。毕竟K-D树的O(sqrt(n))的时间...

【BZOJ 2648/2716】SJY摆棋子

Description这天,SJY显得无聊。在家自己玩。在一个棋盘上,有N个黑色棋子。他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子。此...

【BZOJ 2716/2648】 [Violet 3]天使玩偶

kd-tree模板题~双倍经验~

【BZOJ1941】【SDOI2010】Hide and Seek、KDTree【数组版】 模板、

KDT数组版模板!数组版数组版

BZOJ 2716 LCT模板题

找不到比这更适合当模板题的题了。#include #include #include #define mod 51061 #define ll unsigned int using namespace...

[BZOJ2716][天使玩偶angel][CDQ分治]

[BZOJ2716][天使玩偶angel][CDQ分治]题目大意: 先给出n个点, 然后有m个操作, (1, x, y) 表示查询离(x, y)最近点的曼哈顿距离, (2, x, y) 表示插入点...

bzoj2648 SJY摆棋子

kdtree
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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