【BZOJ 4520】[Cqoi2016]K远点对 kd-tree

236 篇文章 0 订阅
3 篇文章 0 订阅
这篇博客探讨了在BZOJ 4520题目中使用kd-tree解决K远点对问题的复杂度分析。作者指出尽管kd-tree的搜索复杂度看似迷惑,但其强大的剪枝能力使得在实际应用中暴力求解也能取得意料之外的效果,建议在遇到类似问题时考虑使用暴力方法。
摘要由CSDN通过智能技术生成

迷之复杂度。。。。。。

总感觉kd-tree的复杂度很迷,毕竟搜索嘛,可是剪枝居然这么强也是够了,所以我感觉以后遇见kd-tree的题目真的就别想什么T了,暴力出奇迹

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<algorithm>
#define inf 0x3fffffff
#define maxn 200021
#define ls nod[u].l
#define rs nod[u].r
#define LL long long
using namespace std;
int n,K,pos,rt;LL dx,dy;
priority_queue<LL,vector<LL>,greater<LL> >q;
struct node{
	int l,r;
	LL Max[2],Min[2],d[2];
	bool operator<(const node& y)const{
		return d[pos]==y.d[pos] ? d[pos^1]<y.d[pos^1] : d[pos]<y.d[pos];
	}
}nod[maxn];
void push_up(int u){
	for(int i=0;i<2;i++){
		nod[u].Max[i]=max(nod[u].d[i],max(nod[ls].Max[i],nod[rs].Max[i]));
		nod[u].Min[i]=min(nod[u].d[i],min(nod[ls].Min[i],nod[rs].Min[i]));
	}
}
int build(int l,int r,int k){
	if(l>r)return 0;
	int mid=l+r>>1;
	pos=k;nth_element(nod+l+1,nod+1+mid,nod+1+r);
	if(l<mid)nod[mid].l=build(l,mid-1,k^1);
	if(r>mid)nod[mid].r=build(mid+1,r,k^1);
	push_up(mid);
	return mid;
}
inline LL sqr(LL x){return x*x;}
inline LL Q(int a){return sqr(nod[a].d[0]-dx)+sqr(nod[a].d[1]-dy);}
inline LL dis2(LL a,LL b){return sqr(a-dx)+sqr(b-dy);}
LL guess(int a){
	LL ans=0;
	ans=max(ans,dis2(nod[a].Max[0],nod[a].Max[1]));
	ans=max(ans,dis2(nod[a].Max[0],nod[a].Min[1]));
	ans=max(ans,dis2(nod[a].Min[0],nod[a].Max[1]));
	ans=max(ans,dis2(nod[a].Min[0],nod[a].Min[1]));
	return ans;
}
void query(int u){
	if(!u)return;
	LL ans=Q(u),ansl=guess(nod[u].l),ansr=guess(nod[u].r);
	if(ans>q.top())q.pop(),q.push(ans);
	if(ansl>ansr){
		if(ansl>q.top())query(ls);
		if(ansr>q.top())query(rs);
	}else{
		if(ansr>q.top())query(rs);
		if(ansl>q.top())query(ls);
	}
}
int main(){
	nod[0].Min[0]=nod[0].Min[1]=inf;
	nod[0].Max[0]=nod[0].Max[1]=-inf;
	scanf("%d%d",&n,&K);for(int i=1;i<=2*K;i++)q.push(0);
	for(int i=1;i<=n;i++)scanf("%lld%lld",&nod[i].d[0],&nod[i].d[1]);
	rt=build(1,n,0);
	for(int i=1;i<=n;i++){
		dx=nod[i].d[0],dy=nod[i].d[1];
		query(rt);
	}printf("%lld",q.top());
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值