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

题目链接: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 second
	const 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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值