loj #2043. 「CQOI2016」K 远点对(KDTree)

来源:互联网 发布:adobe creative软件 编辑:程序博客网 时间:2024/06/11 17:10

题目链接:https://loj.ac/problem/2043


KDTree板题?貌似会就能过哦。


代码:

#include<bits/stdc++.h>using namespace std;typedef long long ll;namespace KD_Tree{#define x first#define y secondconst int MAXN=2e5+5;const ll inf=0x3f3f3f3f3f3f3f3f;struct _{ll dis;_(ll _dis=0):dis(_dis){}bool operator < (const _ &a)const{return dis>a.dis;}};priority_queue<_> Q;    struct node    {        node *ch[2];        ll d[2],mx[2],my[2],size;//d表示这个点的坐标[0]->x,[1]->y,mx表示这个平面的x的范围,my表示这个平面的y的范围        inline void push_up()        {            size=1;            for(int i=0;i<=1;i++)            {                if(ch[i])                {                    mx[0]=min(mx[0],ch[i]->mx[0]);                    mx[1]=max(mx[1],ch[i]->mx[1]);                    my[0]=min(my[0],ch[i]->my[0]);                    my[1]=max(my[1],ch[i]->my[1]);                    size+=ch[i]->size;                }            }        }    }pool_node[MAXN],*pool_top=pool_node;    node *del_pool[MAXN],**del_top=del_pool;    inline node* newnode()    {        return del_top==del_pool?++pool_top:*(del_top--);    }    typedef pair<ll,ll> Point;    inline bool cmp_x(const Point &a,const Point &b) {return a.x<b.x;}    inline bool cmp_y(const Point &a,const Point &b) {return a.y<b.y;}    node **rebuild_need;    int rebuild_d;    Point stk[MAXN];    int point_cnt;    //用于最开始建树,可以不用直接插点,方法为build(1,point_cnt,0),保证点在stk数组中    node* build(int l,int r,bool f)    {        int mid=(l+r)>>1;        node *o=newnode();        nth_element(stk+l,stk+mid,stk+r+1,!f?cmp_x:cmp_y);        o->d[0]=o->mx[0]=o->mx[1]=stk[mid].x;        o->d[1]=o->my[0]=o->my[1]=stk[mid].y;        o->ch[0]=l<mid?build(l,mid-1,f^1):0;        o->ch[1]=mid<r?build(mid+1,r,f^1):0;        o->push_up();        return o;    }    Point P;    ll calc_mx(node *o)    {        ll ret=0;        ret+=(max(P.x-o->mx[0],0LL)+max(o->mx[1]-P.x,0LL))*(max(P.x-o->mx[0],0LL)+max(o->mx[1]-P.x,0LL));        ret+=(max(P.y-o->my[0],0LL)+max(o->my[1]-P.y,0LL))*(max(P.y-o->my[0],0LL)+max(o->my[1]-P.y,0LL));return ret;    }    node *root;void Query(node *o)    {ll dis=(P.x-o->d[0])*(P.x-o->d[0])+(P.y-o->d[1])*(P.y-o->d[1]);if(dis>Q.top().dis){Q.pop();Q.push(_(dis));}ll dl=o->ch[0]?calc_mx(o->ch[0]):-inf;        ll dr=o->ch[1]?calc_mx(o->ch[1]):-inf;if(dl>dr){if(dl>Q.top().dis)Query(o->ch[0]);if(dr>Q.top().dis)Query(o->ch[1]);}else{if(dr>Q.top().dis)Query(o->ch[1]);if(dl>Q.top().dis)Query(o->ch[0]);}        return ;    }    void init()//用于初始化    {        del_top=del_pool,pool_top=pool_node;    }}using namespace KD_Tree;int main(){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);int n,k;init();scanf("%d%d",&n,&k);k<<=1;for(int i=1;i<=n;i++){scanf("%lld%lld",&stk[i].x,&stk[i].y);}root=build(1,n,1);for(int i=1;i<=k;i++){Q.push(_(0));}for(int i=1;i<=n;i++){P=make_pair(stk[i].x,stk[i].y);Query(root);}printf("%lld\n",Q.top().dis);return 0;}