bzoj-1941 Hide and Seek

原创 2015年11月20日 22:34:27

题意:

给出平面上n个点,求距离每个点最大距离减最小距离(不算自己)的最小值;

n<=500000;


题解:

今天写了两道KDTree然而另一道被常数卡飞。。所以就写这个不需要重构的题解吧;

虽说如此但是这毕竟还是裸题啊。。

KD树在实现的时候需要注意一些问题。。

就是每次到了下一个深度都要换一个不同的比较函数来进行排序建树;

否则似乎就变成和线段树/平衡树一样的东西了,那样剪枝的效果会大大下降;

c++的库函数中有nth_element这个神物来直接找到中间值,并分别将小于和大于的元素放在两边

有了这个似乎真是省去了不少麻烦呢。。

然后就是KD树的强剪枝方法,对于每个结点维护子树内所有点覆盖到的最大的K维几何体;

剪枝条件就是计算这个几何体离查询点的最大/最小距离,然后规划先搜索那个子树,减掉该剪的枝就可以了;

因为这道题没有插入所有还是很兹瓷的!时间复杂度?不知道哦!


代码:


#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 500100
using namespace std;
struct Point
{
	int x[2];
	friend int dis(Point a,Point b)
	{
		return abs(a.x[0]-b.x[0])+abs(a.x[1]-b.x[1]);
	}
}a[N],low[N],upp[N];
int ch[N][2];
int k,ban,af,ac;
bool cmp(Point a,Point b)
{
	if(a.x[k]!=b.x[k])
	return a.x[k]<b.x[k];
	return a.x[!k]<b.x[!k];
}
void Pushup(int rt)
{
	if(ch[rt][0])
	{
		low[rt].x[0]=min(low[rt].x[0],low[ch[rt][0]].x[0]);
		low[rt].x[1]=min(low[rt].x[1],low[ch[rt][0]].x[1]);
		upp[rt].x[0]=max(upp[rt].x[0],upp[ch[rt][0]].x[0]);
		upp[rt].x[1]=max(upp[rt].x[1],upp[ch[rt][0]].x[1]);
	}
	if(ch[rt][1])
	{
		low[rt].x[0]=min(low[rt].x[0],low[ch[rt][1]].x[0]);
		low[rt].x[1]=min(low[rt].x[1],low[ch[rt][1]].x[1]);
		upp[rt].x[0]=max(upp[rt].x[0],upp[ch[rt][1]].x[0]);
		upp[rt].x[1]=max(upp[rt].x[1],upp[ch[rt][1]].x[1]);
	}
}
int Build(int l,int r,int deep)
{
	if(l>r)	return 0;
	int mid=l+r>>1;
	k=deep&1;
	nth_element(a+l,a+mid,a+r+1,cmp);
	ch[mid][0]=Build(l,mid-1,deep+1);
	ch[mid][1]=Build(mid+1,r,deep+1);
	low[mid]=upp[mid]=a[mid];
	Pushup(mid);
	return mid;
}
int calf(int rt)
{
	return max(abs(low[rt].x[0]-a[ban].x[0]),abs(a[ban].x[0]-upp[rt].x[0]))+
		max(abs(low[rt].x[1]-a[ban].x[1]),abs(a[ban].x[1]-upp[rt].x[1]));
}
int calc(int rt)
{
	return max(low[rt].x[0]-a[ban].x[0],0)+max(a[ban].x[0]-upp[rt].x[0],0)+
		max(low[rt].x[1]-a[ban].x[1],0)+max(a[ban].x[1]-upp[rt].x[1],0);
}
void queryf(int rt)
{
	if(!rt)	return ;
	af=max(af,dis(a[ban],a[rt]));
	int l=calf(ch[rt][0]),r=calf(ch[rt][1]);
	if(l>r)
	{
		if(l>af)	queryf(ch[rt][0]);
		if(r>af)	queryf(ch[rt][1]);
	}
	else
	{
		if(r>af)	queryf(ch[rt][1]);
		if(l>af)	queryf(ch[rt][0]);
	}
}
void queryc(int rt)
{
	if(!rt)	return ;
	if(rt!=ban)
		ac=min(ac,dis(a[ban],a[rt]));
	int l=calc(ch[rt][0]),r=calc(ch[rt][1]);
	if(l<r)
	{
		if(l<ac)	queryc(ch[rt][0]);
		if(r<ac)	queryc(ch[rt][1]);
	}
	else
	{
		if(r<ac)	queryc(ch[rt][1]);
		if(l<ac)	queryc(ch[rt][0]);
	}
}
int main()
{
	int n,m,i,j,k,x,y,rt,ans;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
		scanf("%d%d",a[i].x,a[i].x+1);
	rt=Build(1,n,0);
	ans=0x3f3f3f3f;
	for(i=1;i<=n;i++)
	{
		ban=i;
		af=0;
		ac=0x3f3f3f3f;
		queryf(rt);
		queryc(rt);
		ans=min(ans,af-ac);
	}
	printf("%d\n",ans);
	return 0;
}



[BZOJ1941][Sdoi2010]Hide and Seek(kd-tree)

题目描述传送门题解sdoi竟然会考kd-tree裸题= =惊恐脸 询问每一个点的最近点和最远点然后更新答案就行了代码#include #include #include #include #incl...

[BZOJ1941][Sdoi2010]Hide and Seek

Kdtree第一题.讲一下Kdtree: Kdtree的用途是对高维向量(点)进行各种索引.
  • Zvezda_
  • Zvezda_
  • 2016年02月23日 22:08
  • 601

[bzoj1941][SDOI2010]Hide and Seek

1941: [Sdoi2010]Hide and SeekTime Limit: 16 Sec Memory Limit: 162 MB Submit: 755 Solved: 425 [Su...

bzoj1941: [Sdoi2010]Hide and Seek

KD-tree!!!终于开始写KD-tree了。。(太弱了。。) KD-tree支持建树、插入一个点均摊O(logn)(替罪羊树实现)、查询距某点k近点O(sqrt(n))。 本题只要建树后对每个点求...
  • Miao_zc
  • Miao_zc
  • 2016年05月12日 15:30
  • 313

BZOJ 1941 [Sdoi2010] Hide and Seek

KDtree

BZOJ 1941 Sdoi2010 Hide and Seek K-Dimensional-Tree

题目大意:给定平面上的n个点,定义距离为曼哈顿距离,求一个点到其他所有点的最大距离与最小距离之差最小 KDTree……这东西好神啊 注意计算最小距离的时候不能把自己也算进去= = #includ...
  • PoPoQQQ
  • PoPoQQQ
  • 2015年04月15日 11:17
  • 1294

【SDOI2010】【BZOJ1941】Hide and Seek

Description小猪iPig在PKU刚上完了无聊的猪性代数课,天资聪慧的iPig被这门对他来说无比简单的课弄得非常寂寞,为了消除寂寞感,他决定和他的好朋友giPi(鸡皮)玩一个更加寂寞的游戏—捉...

【SDOI2010】bzoj1941 Hide and Seek

kdtree
  • sdfzyhx
  • sdfzyhx
  • 2016年12月31日 16:29
  • 138

【BZOJ1941】【SDOI2010】Hide and Seek、KDTree【数组版】 模板、

KDT数组版模板!数组版数组版
  • Vmurder
  • Vmurder
  • 2014年12月25日 20:23
  • 1084

Bzoj1941:[Sdoi2010]Hide and Seek:K-D-Tree

题目链接:1941:[Sdoi2010]Hide and Seek 和上一个题一样是个模板题QwQ #include #include #include #include #define rep(...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:bzoj-1941 Hide and Seek
举报原因:
原因补充:

(最多只允许输入30个字)