kd-tree

纪念oi路上第一颗kd-tree

板子题

说说主要思想,考虑二叉搜索树来统计答案,玄学乱搞的地方就是减枝了。通过不断换维(不一定一直换,只要保证时间空间都尽量优就行),用<algorithm>库中的nth_element来找到中位数式的元素,此元素就是二叉搜索树对应的元素。最大值用A*思想减支,最小值用边界判断。还有值得学习的地方是判断先搜左儿子还是右儿子

/*
	从直系的直系的学长颓来的板子
*/
#include<algorithm>
#include<cstdio>
#include<iostream>
#include<cmath>
#define MAXN 100010
#define INF 0x7fffffff
using namespace std;
int opt;
struct ww{
	int wg[2];
	friend bool operator <(const ww &a,const ww &b){
		return a.wg[opt]<b.wg[opt];
	}
}wen[MAXN];
inline int minn(int a,int b){return a<b?a:b; }
inline int maxn(int a,int b){return a>b?a:b; }
int n;
struct KDTREE{
	int num,root,res;
	struct TREE{
		ww wen;
		int ls,rs;
		int mx[2],mn[2];
		#define ls(u) (tr[u].ls)
		#define rs(u) (tr[u].rs)
	}tr[MAXN];
	inline int mht(ww a,TREE b){
		return abs(a.wg[0]-b.wen.wg[0])+abs(a.wg[1]-b.wen.wg[1]); 
	}
	inline int mxdis(ww a,TREE b){
		int x=maxn(abs(a.wg[0]-b.mn[0]),abs(a.wg[0]-b.mx[0]));
		int y=maxn(abs(a.wg[1]-b.mn[1]),abs(a.wg[1]-b.mx[1]));
		return x+y;
	}
	inline int mndis(ww a,TREE b){//只减掉了在边界外的树枝
		int x=maxn(b.mn[0]-a.wg[0],0)+maxn(a.wg[0]-b.mx[0],0);
		int y=maxn(b.mn[1]-a.wg[1],0)+maxn(a.wg[1]-b.mx[1],0);
		return x+y;
	}
	void qw_mx(ww a,int u,int knd){
		if(!u)return ;int tmp;
		if((tmp=mht(a,tr[u]))>res)res=tmp;
		int lch=ls(u),rch=rs(u);
		if(a.wg[knd]<tr[lch].wen.wg[knd])swap(lch,rch);//
		if(mxdis(a,tr[lch])>res)qw_mx(a,lch,knd^1);
		if(mxdis(a,tr[rch])>res)qw_mx(a,rch,knd^1);
	}
	int qw_mx(ww a){
		res=-INF;
		qw_mx(a,root,0);
		return res;
	}
	void qw_mn(ww a,int u,int knd){
		//printf("u=%d knd=%d\n",u,knd);
		if(!u)return ;int tmp;
		if((tmp=mht(a,tr[u]))<res&&tmp)res=tmp;
		//cout<<tmp<<endl;
		int lch=ls(u),rch=rs(u);
		//cout<<lch<<" "<<rch<<endl;
		if(a.wg[knd]>tr[lch].wen.wg[knd])swap(lch,rch);//
		if(mndis(a,tr[lch])<res)qw_mn(a,lch,knd^1);
		if(mndis(a,tr[rch])<res)qw_mn(a,rch,knd^1);
	}
	int qw_mn(ww a){
		//cout<<a.wg[0]<<" "<<a.wg[1]<<endl;
		res=INF;
		qw_mn(a,root,0);
		//cout<<"STO"<<endl;
		return res;
	}
	void up(int u){
		if(ls(u))
			for(int i=0;i<2;++i){
				tr[u].mn[i]=minn(tr[u].mn[i],tr[ls(u)].mn[i]);
				tr[u].mx[i]=maxn(tr[u].mx[i],tr[ls(u)].mx[i]);
			}
		if(rs(u))
			for(int i=0;i<2;++i){
				tr[u].mn[i]=minn(tr[u].mn[i],tr[rs(u)].mn[i]);
				tr[u].mx[i]=maxn(tr[u].mx[i],tr[rs(u)].mx[i]);
			}
	}
	void build(int &u,int l,int r,int knd){
		if(r<l)return ;
		u=++num;opt=knd;
		int mid=l+r>>1;
		nth_element(wen+l,wen+mid,wen+r+1);
		tr[u].wen=wen[mid];
		for(int i=0;i<2;++i)
			tr[u].mn[i]=tr[u].mx[i]=wen[mid].wg[i];
		build(ls(u),l,mid-1,knd^1); 
		build(rs(u),mid+1,r,knd^1);
		up(u);
		//cout<<u<<" "<<tr[u].wen.wg[0]<<" "<<tr[u].wen.wg[1]<<endl;
		//cout<<tr[u].mn[0]<<" "<<tr[u].mn[1]<<" "<<tr[u].mx[0]<<" "<<tr[u].mx[1]<<endl;
	}
	void build(){
		root=num=0;
		build(root,1,n,0);
	}
}QwQ;
int ans=INF;
int main(){
//	freopen("da.in","r",stdin);
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		scanf("%d%d",&wen[i].wg[0],&wen[i].wg[1]);
	QwQ.build();
	for(int i=1;i<=n;++i){
		ans=minn(ans,QwQ.qw_mx(wen[i])-QwQ.qw_mn(wen[i]));
		//cout<<"HHHHHHHHH"<<QwQ.qw_mx(wen[i])<<" "<<QwQ.qw_mn(wen[i])<<endl;
	}
	printf("%d\n",ans);
}

 

上一篇:golang并发控制方法WaitGroup


下一篇:golang通知协程退出