洛谷传送门
BZOJ传送门
题目描述
iPig在大肥猪学校刚上完了无聊的猪文课,天资聪慧的iPig被这门对他来说无比简单的课弄得非常寂寞,为了消除寂寞感,他决定和他的好朋友giPi(鸡皮)玩一个更加寂寞的游戏——捉迷藏。
但是,他们觉得,玩普通的捉迷藏没什么意思,还是不够寂寞,于是,他们决定玩寂寞无比的螃蟹版捉迷藏,顾名思义,就是说他们在玩游戏的时候只能沿水平或垂直方向走。一番寂寞的剪刀石头布后,他们决定iPig去捉giPi。由于他们都很熟悉大肥猪学校的地形了,所以giPi只会躲在大肥猪学校内 N N N个隐秘地点,显然iPig也只会在那 N N N个地点内找giPi。游戏一开始,他们从这 N N N个隐秘地点之中选定一个地点,iPig保持不动,然后giPi用 30 30 30秒的时间逃离现场(显然,giPi不会呆在原地)。然后iPig会随机地去找giPi,直到找到为止。由于iPig很懒,所以他到总是走最短的路径,而且,他选择起始点不是随便选的,他想找一个地点,使得该地点到(除了这个地点以外的)最远的地点和最近的地点的距离差最小。iPig现在想知道这个距离差最小是多少。
由于iPig现在手上没有电脑,所以不能编程解决这个如此简单的问题,所以他马上打了个电话,要求你帮他解决这个问题。iPig告诉了你大肥猪学校的 N N N个隐秘地点的坐标,请你编程求出iPig的问题。
输入输出格式
输入格式:
第 1 1 1行:一个整数 N N N;
第 2 ∼ ( N + 1 ) 2 \sim (N + 1) 2∼(N+1)行:每行两个整数 X i , Y i X_i,Y_i Xi,Yi,表示第 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 2≤N≤1000;
100%的数据中, 2 ≤ N ≤ 100000 , 0 ≤ X i , Y i ≤ 100000000 2 \leq N \leq 100000,0 \leq Xi, Yi \leq 100000000 2≤N≤100000,0≤Xi,Yi≤100000000。
数据保证没有重点。
解题分析
求曼哈顿距离最小最大值, K − D T r e e K-D\ Tree K−D Tree区域求 m i n , m a x min,max 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);
}