[Luogu P2479] [BZOJ 1941] [SDOI2010]捉迷藏

版权声明:欢迎转载蒟蒻博客,但请注明出处: https://blog.csdn.net/LPA20020220/article/details/82961441

洛谷传送门

BZOJ传送门

题目描述

iPig在大肥猪学校刚上完了无聊的猪文课,天资聪慧的iPig被这门对他来说无比简单的课弄得非常寂寞,为了消除寂寞感,他决定和他的好朋友giPi(鸡皮)玩一个更加寂寞的游戏——捉迷藏。

但是,他们觉得,玩普通的捉迷藏没什么意思,还是不够寂寞,于是,他们决定玩寂寞无比的螃蟹版捉迷藏,顾名思义,就是说他们在玩游戏的时候只能沿水平或垂直方向走。一番寂寞的剪刀石头布后,他们决定iPig去捉giPi。由于他们都很熟悉大肥猪学校的地形了,所以giPi只会躲在大肥猪学校内 N N 个隐秘地点,显然iPig也只会在那 N N 个地点内找giPi。游戏一开始,他们从这 N N 个隐秘地点之中选定一个地点,iPig保持不动,然后giPi用 30 30 秒的时间逃离现场(显然,giPi不会呆在原地)。然后iPig会随机地去找giPi,直到找到为止。由于iPig很懒,所以他到总是走最短的路径,而且,他选择起始点不是随便选的,他想找一个地点,使得该地点到(除了这个地点以外的)最远的地点和最近的地点的距离差最小。iPig现在想知道这个距离差最小是多少。

由于iPig现在手上没有电脑,所以不能编程解决这个如此简单的问题,所以他马上打了个电话,要求你帮他解决这个问题。iPig告诉了你大肥猪学校的 N N 个隐秘地点的坐标,请你编程求出iPig的问题。

输入输出格式

输入格式:

输入文件hideseek.in

1 1 行:一个整数 N N

2 ( N + 1 ) 2 \sim (N + 1) 行:每行两个整数 X i Y i X_i,Y_i ,表示第 i i 个地点的坐标。

输出格式:

输出文件hideseek.out有且仅有一行:一个整数,为距离差的最小值。

输入输出样例

输入样例#1:

4
0 0
1 0
0 1
1 1

输出样例#1:

1

说明

30%的数据中, 2 N 1000 2 \leq N \leq 1000

100%的数据中, 2 N 100000 , 0 X i , Y i 100000000 2 \leq N \leq 100000,0 \leq Xi, Yi \leq 100000000

数据保证没有重点。

解题分析

求曼哈顿距离最小最大值, K D   T r e e K-D\ Tree 区域求 m i n , m a x min,max 的代码稍微改下就好了。

代码如下:

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 500050
#define INF 200000005
using std::max; using std::min;
template <class T>
IN void in(T &x)
{
	x = 0; R char c = gc;
	for (; !isdigit(c); c = gc);
	for (;  isdigit(c); c = gc)
	x = (x << 1) + (x << 3) + c - 48;
}
struct Node {int son[2], lim[2][2], cood[2];} tree[MX];
int dim, dot, mn, mx, root, x, y;
IN bool operator < (const Node &x, const Node &y)
{return x.cood[dim] == y.cood[dim] ? x.cood[dim ^ 1] < y.cood[dim ^ 1] : x.cood[dim] < y.cood[dim];}
namespace KDT
{
	#define ls tree[now].son[0]
	#define rs tree[now].son[1]
	IN void pushup(R int now)
	{
		tree[now].lim[0][0] = tree[now].lim[0][1] = tree[now].cood[0];
		tree[now].lim[1][0] = tree[now].lim[1][1] = tree[now].cood[1];
		if(ls)
		{
			tree[now].lim[0][0] = min(tree[now].lim[0][0], tree[ls].lim[0][0]);
			tree[now].lim[0][1] = max(tree[now].lim[0][1], tree[ls].lim[0][1]);
			tree[now].lim[1][0] = min(tree[now].lim[1][0], tree[ls].lim[1][0]);
			tree[now].lim[1][1] = max(tree[now].lim[1][1], tree[ls].lim[1][1]);
		}
		if(rs)
		{
			tree[now].lim[0][0] = min(tree[now].lim[0][0], tree[rs].lim[0][0]);
			tree[now].lim[0][1] = max(tree[now].lim[0][1], tree[rs].lim[0][1]);
			tree[now].lim[1][0] = min(tree[now].lim[1][0], tree[rs].lim[1][0]);
			tree[now].lim[1][1] = max(tree[now].lim[1][1], tree[rs].lim[1][1]);
		}
	}
	int build(R int lef, R int rig, R int d)
	{
		dim = d; R int now = lef + rig >> 1;
		std::nth_element(tree + lef, tree + now, tree + rig + 1);
		if(lef < now) ls = build(lef, now - 1, d ^ 1);
		if(now < rig) rs = build(now + 1, rig, d ^ 1);
		pushup(now); return now;
	}
	IN int getmx(R int id)
	{
		int delx = max(std::abs(x - tree[id].lim[0][0]), std::abs(x - tree[id].lim[0][1]));
		int dely = max(std::abs(y - tree[id].lim[1][0]), std::abs(y - tree[id].lim[1][1]));
		return delx + dely;
	}
	IN int getmn(R int id)
	{
		int delx = 0, dely = 0;
		if(x >= tree[id].lim[0][0] && x <= tree[id].lim[0][1]) delx = 0;
		else if(x < tree[id].lim[0][0]) delx = tree[id].lim[0][0] - x;
		else delx = x - tree[id].lim[0][1];
		if(y >= tree[id].lim[1][0] && y <= tree[id].lim[1][1]) dely = 0;
		else if(y < tree[id].lim[1][0]) dely = tree[id].lim[1][0] - y;
		else dely = y - tree[id].lim[1][1];
		return delx + dely;
	}
	IN int getdis(R int id) {return std::abs(x - tree[id].cood[0]) + std::abs(y - tree[id].cood[1]);}
	void solvemn (R int now)
	{
		int dl = INF, dr = INF, dnow;
		dnow = getdis(now);
		if(ls) dl = getmn(ls);
		if(rs) dr = getmn(rs);
		if(dnow < mn && dnow) mn = dnow;
		if(dl < dr)
		{
			if(dl < mn) solvemn(ls);
			if(dr < mn) solvemn(rs);
		}
		else
		{
			if(dr < mn) solvemn(rs);
			if(dl < mn) solvemn(ls);
		}
	}
	void solvemx(R int now)
	{
		int dl = -1, dr = -1, dnow;
		dnow = getdis(now);
		if(ls) dl = getmx(ls);
		if(rs) dr = getmx(rs);
		if(dnow > mx) mx = dnow;
		if(dl > dr)
		{
			if(dl > mx) solvemx(ls);
			if(dr > mx) solvemx(rs);
		}
		else
		{
			if(dr > mx) solvemx(rs);
			if(dl > mx) solvemx(ls);
		}
	}
	#undef ls
	#undef rs
}
int main(void)
{
	in(dot); int ans = INF + 5;
	for (R int i = 1; i <= dot; ++i) in(tree[i].cood[0]), in(tree[i].cood[1]);
	root = KDT::build(1, dot, 0);
	for (R int i = 1; i <=  dot; ++i)
	{
		mx = 0; mn = INF;
		x = tree[i].cood[0], y = tree[i].cood[1];
		KDT::solvemn(root);
		KDT::solvemx(root);
		ans = min(ans, mx - mn);
	}
	printf("%d", ans);
}

猜你喜欢

转载自blog.csdn.net/LPA20020220/article/details/82961441