【BZOJ 2716&2648】[Violet 3]天使玩偶 k-d tree

236 篇文章 0 订阅
3 篇文章 0 订阅

闲来无事就去看了看k-dtree顺便刷了个版,其实谈谈自己对这个数据结构的感受,其实感觉与其说是一个漂亮的数据结构还不如说是一个优美的搜索,就是讲每一块在建树的时候就按照一定的顺序分开来建这样的话,我们在查找的时候就可以写一个估价函数来节约掉很多不必要的搜索。

这里来讲讲查询,毕竟是自己一开始最搞不懂的地方。首先我们到了根节点然后发现这个图被分成了两块,如果这个点在其中一个块内,毫无疑问,离他最近的节点很有可能就在这个快里面,返回0,必须访问。那如果不在里面呢?由于之前我们记录了一个max和min这就是在这一块内最理想的情况下里查询点的距离了,比较哪个理想情况更理想,那么可能性就更大,就先遍历,如果在最优情况下都比我们当前得到的ans(一开始为正无穷)还大,自然就不必遍历了,就节省了很多不必要的遍历,但就刚才说的可以看出kd树应该是很容易被卡掉吧,如果出题人想得话。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define inf 0x3f3f3f3f
#define maxn 1000020 
#define ls nod[u].l
#define rs nod[u].r
#define cmax(a,b) (a=max(a,(b)))
#define cmin(a,b) (a=min(a,(b)))
using namespace std;
void read(int& x){
	x=0;char c=getchar();int f=1;
	for(;c>'9'||c<'0';c=getchar())if(c=='-')f=-1;
	for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';x*=f;
}
int n,m,pos,x[2],ans,rt;
struct node{
	int d[2],mx[2],mi[2],l,r;
	node():l(0),r(0){}
	bool operator<(const node& b)const{
		return d[pos]==b.d[pos] ? d[pos^1]<b.d[pos^1] : d[pos]<b.d[pos];
	}
}nod[maxn];
void push_up(int u){
	for(int i=0;i<2;i++){
		cmax(nod[u].mx[i],max(nod[ls].mx[i],nod[rs].mx[i]));
		cmin(nod[u].mi[i],min(nod[ls].mi[i],nod[rs].mi[i]));
	}
}
int Q(int a){
	return abs(nod[a].d[0]-x[0])+abs(nod[a].d[1]-x[1]);
}
int guess(int u,int ans=0){
	if(!u)return inf;
	for(int i=0;i<2;i++)ans+=max(0,nod[u].mi[i]-x[i])+max(0,x[i]-nod[u].mx[i]);
	return ans;
}
int build(int l,int r,int k){
	int mid=l+r>>1;
	pos=k;
	nth_element(nod+1+l,nod+1+mid,nod+1+r);
	for(int i=0;i<2;i++)nod[mid].mx[i]=nod[mid].mi[i]=nod[mid].d[i];
	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;
}
void insert(int& u,int k){
	if(u==0){
		u=++n;
		for(int i=0;i<2;i++)nod[u].d[i]=nod[u].mi[i]=nod[u].mx[i]=x[i];
		return;
	}
	if(x[k]>nod[u].d[k])insert(rs,k^1);
	else insert(ls,k^1);
	push_up(u);
}
void query(int u){
	if(!u)return;
	int d0=Q(u),d1=guess(ls),d2=guess(rs);
	cmin(ans,d0);
	if(d1<d2){
		if(ans>d1)query(ls);
		if(ans>d2)query(rs);
	}else{
		if(ans>d2)query(rs);
		if(ans>d1)query(ls);
	}
}
int main(){
	read(n),read(m);
	nod[0].mi[0]=nod[0].mi[1]=inf,nod[0].mx[0]=nod[0].mx[1]=-inf;
	for(int i=1;i<=n;i++)read(nod[i].d[0]),read(nod[i].d[1]);
	rt=build(1,n,0);int a,b,c;
	while(m--){
		read(a),read(x[0]),read(x[1]);
		if(a==2){
			ans=inf;query(rt);
			printf("%d\n",ans);
		}else insert(rt,0);
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值