HYSBZ1941-Hide and Seek

来源:互联网 发布:退火算法 matlab 编辑:程序博客网 时间:2024/06/06 18:47

[Sdoi2010]Hide and Seek

Time Limit: 16 Sec  Memory Limit: 162 MB
Submit: 1435  Solved: 773
[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

SDOI2010 第二轮Day 1



解题思路:kd-tree


#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <cctype>#include <map>#include <cmath>#include <set>#include <stack>#include <queue>#include <vector>#include <bitset>#include <functional>using namespace std;#define LL long longconst int INF = 0x3f3f3f3f;const int N = 2000000 + 5;const int demension = 2;//二维struct node{int pos[demension];int ma[demension], mi[demension];int l, r;}a[N], x;int cmpDem;//以第cmpDem维作比较int root, n, ans, ans1, ans2;bool cmp(const node &a, const node&b){if (a.pos[cmpDem] != b.pos[cmpDem]) return a.pos[cmpDem] < b.pos[cmpDem];else return a.pos[!cmpDem] < b.pos[!cmpDem];}void Merge(int k){for (int i = 0; i < demension; i++){if (a[k].l){a[k].ma[i] = max(a[k].ma[i], a[a[k].l].ma[i]);a[k].mi[i] = min(a[k].mi[i], a[a[k].l].mi[i]);}if (a[k].r){a[k].ma[i] = max(a[k].ma[i], a[a[k].r].ma[i]);a[k].mi[i] = min(a[k].mi[i], a[a[k].r].mi[i]);}}}int build(int l, int r, int k){if (l > r) return 0;int mid = (l + r) / 2;//以第mid个元素为中心排序cmpDem = k;nth_element(a + l, a + mid, a + r + 1, cmp);//左右子树a[mid].l = build(l, mid - 1, k ^ 1);a[mid].r = build(mid + 1, r, k ^ 1);Merge(mid);return mid;}int getdis1(int k){int dis = 0;for (int i = 0; i < demension; i++){if (x.pos[i] < a[k].mi[i]) dis += a[k].mi[i] - x.pos[i];if (x.pos[i] > a[k].ma[i]) dis += x.pos[i] - a[k].ma[i];}return dis;}void query1(int k){int dis = 0;for (int i = 0; i < demension; i++) dis += abs(x.pos[i] - a[k].pos[i]);if (dis) ans1 = min(ans1, dis);int ld = a[k].l ? getdis1(a[k].l) : INF, rd = a[k].r ? getdis1(a[k].r) : INF;if (min(ld, rd) >= ans1) return;if (ld < rd){query1(a[k].l);if (rd < ans1) query1(a[k].r);}else{query1(a[k].r);if (ld < ans1) query1(a[k].l);}}int getdis2(int k){int dis = 0;for (int i = 0; i < demension; i++)dis += max(abs(a[k].mi[i] - x.pos[i]), abs(x.pos[i] - a[k].ma[i]));return dis;}void query2(int k){int dis = 0;for (int i = 0; i < demension; i++) dis += abs(x.pos[i] - a[k].pos[i]);ans2 = max(ans2, dis);int ld = a[k].l ? getdis2(a[k].l) : -1, rd = a[k].r ? getdis2(a[k].r) : -1;if (max(ld, rd) <= ans2) return;if (ld > rd){query2(a[k].l);if (rd > ans2) query2(a[k].r);}else{query2(a[k].r);if (ld > ans2) query2(a[k].l);}}int main(){while (~scanf("%d", &n)){for (int i = 1; i <= n; i++){scanf("%d%d", &a[i].pos[0], &a[i].pos[1]);a[i].l = a[i].r = 0;a[i].ma[0] = a[i].mi[0] = a[i].pos[0];a[i].ma[1] = a[i].mi[1] = a[i].pos[1];}root = build(1, n, 0);ans = INF;for (int i = 1; i <= n; i++){x = a[i];ans1 = INF, ans2 = 0;query1(root);query2(root);ans = min(ans, ans2 - ans1);}printf("%d\n", ans);}return 0;}