Time Limit: 16 Sec  Memory Limit: 162 MB

Submit: 919  Solved: 497

[Submit][Status][Discuss]

Description

小猪iPig在PKU刚上完了无聊的猪性代数课,天资聪慧的iPig被这门对他来说无比简单的课弄得非常寂寞,为了消除寂寞感,他决定和他的好朋友giPi(鸡皮)玩一个更加寂寞的游戏---捉迷藏。 但是,他们觉得,玩普通的捉迷藏没什么意思,还是不够寂寞,于是,他们决定玩寂寞无比的螃蟹版捉迷藏,顾名思义,就是说他们在玩游戏的时候只能沿水平或垂直方向走。一番寂寞的剪刀石头布后,他们决定iPig去捉giPi。由于他们都很熟悉PKU的地形了,所以giPi只会躲在PKU内n个隐秘地点,显然iPig也只会在那n个地点内找giPi。游戏一开始,他们选定一个地点,iPig保持不动,然后giPi用30秒的时间逃离现场(显然,giPi不会呆在原地)。然后iPig会随机地去找giPi,直到找到为止。由于iPig很懒,所以他到总是走最短的路径,而且,他选择起始点不是随便选的,他想找一个地点,使得该地点到最远的地点和最近的地点的距离差最小。iPig现在想知道这个距离差最小是多少。
由于iPig现在手上没有电脑,所以不能编程解决这个如此简单的问题,所以他马上打了个电话,要求你帮他解决这个问题。iPig告诉了你PKU的n个隐秘地点的坐标,请你编程求出iPig的问题。

Input

第一行输入一个整数N 第2~N+1行,每行两个整数X,Y,表示第i个地点的坐标

Output

一个整数,为距离差的最小值。

Sample Input

4

0 0

1 0

0 1

1 1

Sample Output

1


HINT

对于30%的数据,N<=1000 对于100%的数据,N<=500000,0<=X,Y<=10^8 保证数据没有重点保证N>=2

Source

【题解】

要用KD-tree来做。

如果想学习KD-tree。可以看下这篇我转载的文章

http://blog.csdn.net/harlow_cheng/article/details/52535535

这篇文章用了图片的例子来讲。我觉得挺不错的。

然后程序里面也有适当的注解。

回归这题。

枚举每个点。然后找一个距离该点最远的点。找一个离该点最近的点(除了本身)

然后相减。

(1..n)取min即可。

发现网上的题解都很豪放啊。都不按套路出牌。不是说好的要按照方差来划分的吗????我看到的程序都是按照x和y轮流划分。。

就是0,1,0,1,0,1这样的。。

研究了好久的程序啊。

我说下这题的思路吧。

K-D树不是把“区间”里面的点都划分成左右两部分吗。

我们就用一个ma_x[2],mi_n[2] 来维护这个每个子区间的左上角和右下角的坐标。

然后原本最朴素的是按照方差的划分依据往左往右。

现在我们用两个估价函数就行了。

gujia_max

gujia_min

分别表示往某个方向走最大的曼哈顿距离。

我相信gujia_max都能看得懂的。

我就只讲下gujia_min

这是代码块。

int gujia_min(int rt)
{
int temp = 0;
for (int i = 0; i <= 1; i++)
{
temp += max(0, op.d[i] - t[rt].ma_x[i]);
temp += max(0, t[rt].mi_n[i]- op.d[i]);
}
return temp;
}

其中的op是当前在处理的点。

然后我们用mi_n和max_存储的可以理解为某个子树区域里面点形成的最大矩形。

这个函数可以判断我们当前在处理的点是否在矩形内。

如果在矩形内就返回0.

表示估价函数最小(因为在矩形内,所以“认为这个点极有可能在那个区间内”);

如果不在那个矩形内。就返回到达这个矩形边缘所需要的最小曼哈顿距离。

我想之所以说它是估价。就是因为没办法确定吧。记住这种方法就行啦。

ps:关于如何排除找到的点不是自身的方法。在更新答案的时候。看一下要更新的答案是不是会变成0(因为没有重点,所以如果距离是0,那肯定就是重复的了,则不要更新答案就好了);

【代码】绝对不是网上看到的那种牛逼哄哄的写了一大串结构体的代码:)

#include <cstdio>
#include <algorithm>
#include <cmath> using namespace std; const int MAXN = 501000;
const int INF = 2100000000; struct point
{
int d[2], ma_x[2], mi_n[2], l, r;
}; point t[MAXN],p[MAXN],op; //t是存储kd树的.p则是用于nth_element的排序
int x[MAXN], y[MAXN],n,root,now,temp1,temp2; //now是当前划分的依据 bool cmp(point a, point b)
{
if (a.d[now] < b.d[now])
return true;
return false;
} void push_up(int rt) //更新最大矩形的左上角和右下角。(不一定有这两个点)
{
int l = t[rt].l, r = t[rt].r;
for (int i = 0; i <= 1; i++)
{
if (l)
{
t[rt].ma_x[i] = max(t[rt].ma_x[i], t[l].ma_x[i]);
t[rt].mi_n[i] = min(t[rt].mi_n[i], t[l].mi_n[i]);
}
if (r)
{
t[rt].ma_x[i] = max(t[rt].ma_x[i], t[r].ma_x[i]);
t[rt].mi_n[i] = min(t[rt].mi_n[i], t[r].mi_n[i]);
}
}
} int build(int begin, int end, int fx)
{
int m = (begin + end) >> 1;
now = fx;
nth_element(p + begin, p + m, p + end + 1, cmp); //左闭右开
t[m] = p[m];
for (int i = 0; i <= 1; i++)
t[m].ma_x[i] = t[m].mi_n[i] = t[m].d[i];
if (begin < m)
t[m].l = build(begin, m - 1, 1 - fx);
if (m < end)
t[m].r = build(m + 1, end, 1 - fx);
push_up(m);
return m;
} void input_data()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d%d", &x[i], &y[i]);
p[i].d[0] = x[i];
p[i].d[1] = y[i];
}
root = build(1, n, 0);
} int get_dis(point a, point b)
{
return abs(a.d[0] - b.d[0]) + abs(a.d[1] - b.d[1]);
} int gujia_max(int rt)
{
int temp = 0;
for (int i = 0; i <= 1; i++)
temp += max(abs(op.d[i] - t[rt].ma_x[i]), abs(op.d[i] - t[rt].mi_n[i]));
return temp;
} void query_max(int rt)
{
int dis = get_dis(op, t[rt]);
temp1 = max(dis, temp1);
int gl = -INF, gr = -INF;
int l = t[rt].l, r = t[rt].r;
if (l)
gl = gujia_max(l);
if (r)
gr = gujia_max(r);
if (gl > gr) //并不是说估价完就指定了一个方向!
{
if (gl > temp1)
query_max(l);
if (gr > temp1)
query_max(r);
}
else
{
if (gr > temp1)
query_max(r);
if (gl > temp1)
query_max(l);
}
} int gujia_min(int rt)
{
int temp = 0;
for (int i = 0; i <= 1; i++)
{
temp += max(0, op.d[i] - t[rt].ma_x[i]);
temp += max(0, t[rt].mi_n[i]- op.d[i]);
}
return temp;
} void query_min(int rt)
{
int dis = get_dis(op, t[rt]);
if (dis) //这是排除是本身这个点的方法 即判断距离是否为0;为0就不更新
temp2 = min(temp2, dis);
int l = t[rt].l, r = t[rt].r;
int gl = INF, gr = INF;
if (l)
gl = gujia_min(l);
if (r)
gr = gujia_min(r);
if (gl < gr)
{
if (gl < temp2)
query_min(l);
if (gr < temp2)
query_min(r);
}
else
{
if (gr < temp2)
query_min(r);
if (gl < temp1)
query_min(l);
}
} void get_ans()
{
int ans = INF;
for (int i = 1; i <= n; i++)
{
op.d[0] = x[i];
op.d[1] = y[i];
temp1 = -INF;
query_max(root);
temp2 = INF;
query_min(root);
ans = min(ans, temp1 - temp2);
}
printf("%d\n", ans);
} int main()
{
//freopen("F:\\rush.txt", "r", stdin);
input_data();
get_ans();
return 0;
}

【54.08%】【BZOJ 1941】Hide and Seek的更多相关文章

  1. bzoj:1941: [Sdoi2010]Hide and Seek

    1941: [Sdoi2010]Hide and Seek Time Limit: 16 Sec  Memory Limit: 162 MBSubmit: 531  Solved: 295[Submi ...

  2. bzoj 1941 [Sdoi2010]Hide and Seek——KDtree

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1941 第二道KDtree! 枚举每个点,求出距离它的最远和最近距离.O( n * logn ...

  3. BZOJ 1941: [Sdoi2010]Hide and Seek(k-d Tree)

    Time Limit: 16 Sec  Memory Limit: 162 MBSubmit: 1712  Solved: 932[Submit][Status][Discuss] Descripti ...

  4. BZOJ 1941: [Sdoi2010]Hide and Seek KDtree + 估价函数

    Code: #include<bits/stdc++.h> #define maxn 200000 #define inf 1000000000 using namespace std; ...

  5. 【BZOJ】【1941】【SDOI2010】Hide and Seek

    KD-Tree 一开始看错题了

  6. 【BZOJ-1941】Hide and Seek KD-Tree

    1941: [Sdoi2010]Hide and Seek Time Limit: 16 Sec  Memory Limit: 162 MBSubmit: 830  Solved: 455[Submi ...

  7. 【BZOJ】【2084】【POI2010】Antisymmetry

    Manacher算法 啊……Manacher修改一下就好啦~蛮水的…… Manacher原本是找首尾相同的子串,即回文串,我们这里是要找对应位置不同的“反回文串”(反对称?233) 长度为奇数的肯定不 ...

  8. 【BZOJ 2333 】[SCOI2011]棘手的操作(离线+线段树)

    2333: [SCOI2011]棘手的操作 Description 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i],接下来有如下一些操作: U x y: 加一条边 ...

  9. 【BZOJ】【3083】遥远的国度

    树链剖分/dfs序 其实过了[BZOJ][4034][HAOI2015]T2以后就好搞了…… 链修改+子树查询+换根 其实静态树的换根直接树链剖分就可以搞了…… 因为其实只有一样变了:子树 如果roo ...

随机推荐

  1. [NowCoder]牛客网NOIP赛前集训营-提高组(第七场)

    链接 A.中国式家长2 模拟题,毫无坑点 #include<bits/stdc++.h> #define REP(i,a,b) for(int i(a);i<=(b);++i) #d ...

  2. [NOI.AC#34]palinedrome 字符串hash+贪心

    容易看出,只要从两边往中间扫描,碰到相等的就直接分割然后加入答案即可,判断相等用字符串hash #include<bits/stdc++.h> #define REP(i,a,b) for ...

  3. holder.js如何使用

    holder.js的使用 一.总结 一句话总结:使用:holder.js后面接图片宽高 <img src="holder.js/300x200" /> 1.holder ...

  4. Codefroces 812 B. Sagheer, the Hausmeister

    http://codeforces.com/problemset/problem/812/B B. Sagheer, the Hausmeister time limit per test 1 sec ...

  5. 【Codeforces Round #451 (Div. 2) C】Phone Numbers

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 用map<string,vector > dic;模拟就好. 后缀.翻转一下就变成前缀了. 两重循环剔除这种情况不输出就 ...

  6. Nodejs源代码分析之Path

    今天介绍一下nodejs Path的源代码分析,Path的API文档在https://nodejs.org/dist/latest-v5.x/docs/api/path.html,使用相对简单,在AP ...

  7. ontouch-控件添加ontouch监听事件

    1,代码public class CalculatorViewPager extends ViewPager {}中 package com.android.calculator2; import a ...

  8. 谈谈vector容器的三种遍历方法

    说明:本文仅供学习交流.转载请标明出处.欢迎转载!          vector容器是最简单的顺序容器,其用法相似于数组.实际上vector的底层实现就是採用动态数组.在编敲代码的过程中.经常会变量 ...

  9. Dcloud课程3 什么是HBuilder和MUI

    Dcloud课程3  什么是HBuilder和MUI 一.总结 一句话总结:DCloud(数字天堂)推出一款支持HTML5的Web开发IDE.最大的特点是快.MUI是高性能App的框架,也是目前最接近 ...

  10. JS预解释的总结

    预解释阶段发生在创建了堆内存,让代码执行之前,对当前作用域中带var和function的进行预解释 在浏览器解析执行代码的时候,会提前把带var和function的代码声明或定义,提前放在作用域的最前 ...