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

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

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

#include
#include
#include
#include
#include
#include
#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]>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(d1d1)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;
}


你可能感兴趣的:(ac之路,bzoj,k-d,tree)