【BZOJ-1941】Hide and Seek KD-Tree

1941: [Sdoi2010]Hide and Seek

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

Solution

KDTree模板题...把所有点加入KDTree中,再枚举每一个点,找最远最近,并更新答案即可

需要注意的是,计算最远和最近的两个分开写,而且计算最近点的时候不能计算到自己

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<‘0‘ || ch>‘9‘) {if (ch==‘-‘)f=-1; ch=getchar();}
    while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘; ch=getchar();}
    return x*f;
}
#define inf 0x7fffffff
#define maxn 500010
int n,D,ans;
struct PointNode
{
    int l,r; int d[2],maxx[2],minn[2];
    PointNode (int x=0,int y=0) {l=r=0; d[0]=x,d[1]=y;}
    bool operator < (const PointNode & A) const {return d[D]<A.d[D];}
}p[maxn];
int dis(PointNode A,PointNode B) {return abs(A.d[1]-B.d[1])+abs(A.d[0]-B.d[0]);}
struct KDTreeNode
{
    PointNode tree[maxn<<1],Point;
    int rt,ansMax,ansMin;
    void Update(int now)
        {
            for (int i=0; i<=1; i++)
                {
                    tree[now].minn[i]=tree[now].maxx[i]=tree[now].d[i];
                    if (tree[now].l)
                        tree[now].minn[i]=min(tree[tree[now].l].minn[i],tree[now].minn[i]),              tree[now].maxx[i]=max(tree[tree[now].l].maxx[i],tree[now].maxx[i]);
                    if (tree[now].r)
                        tree[now].minn[i]=min(tree[tree[now].r].minn[i],tree[now].minn[i]),              tree[now].maxx[i]=max(tree[tree[now].r].maxx[i],tree[now].maxx[i]);
                }
        }
    int BuildTree(int l,int r,int dd)
        {
            int mid=(l+r)>>1;
            D=dd; nth_element(p+l,p+mid,p+r+1);
            tree[mid]=p[mid];
            for (int i=0; i<=1; i++) tree[mid].minn[i]=tree[mid].maxx[i]=tree[mid].d[i];
            if (l<mid) tree[mid].l=BuildTree(l,mid-1,dd^1);
            if (r>mid) tree[mid].r=BuildTree(mid+1,r,dd^1);
            Update(mid);
            return mid;
        }
    int disMax(int now)
        {
            if (!now) return -inf;
            int re=0;
            for (int i=0; i<=1; i++)
                re+=max(abs(tree[now].maxx[i]-Point.d[i]),abs(tree[now].minn[i]-Point.d[i]));
            return re;
        }
    int disMin(int now)
        {
            if (!now) return inf;
            int re=0;
            for (int i=0; i<=1; i++) re+=max(0,tree[now].minn[i]-Point.d[i]);
            for (int i=0; i<=1; i++) re+=max(0,Point.d[i]-tree[now].maxx[i]);
            return re;
        }
    void GetMax(int now)
        {
            if (!now) return;
            int dl,dr,d0;
            d0=dis(tree[now],Point);
            ansMax=max(d0,ansMax);
            if (tree[now].l) dl=disMax(tree[now].l);
            if (tree[now].r) dr=disMax(tree[now].r);
            if (dl>dr)
                {
                    if (dl>ansMax) GetMax(tree[now].l);
                    if (dr>ansMax) GetMax(tree[now].r);
                }
            else
                {
                    if (dr>ansMax) GetMax(tree[now].r);
                    if (dl>ansMax) GetMax(tree[now].l);
                }
        }
    void GetMin(int now)
        {
            if (!now) return;
            int dl,dr,d0;
            d0=dis(tree[now],Point);
            if (d0) ansMin=min(ansMin,d0);
            if (tree[now].l) dl=disMin(tree[now].l);
            if (tree[now].r) dr=disMin(tree[now].r);
            if (dl<dr)
                {
                    if (dl<ansMin) GetMin(tree[now].l);
                    if (dr<ansMin) GetMin(tree[now].r);
                }
            else
                {
                    if (dr<ansMin) GetMin(tree[now].r);
                    if (dl<ansMin) GetMin(tree[now].l);
                }
        }
    int QueryMax(PointNode P) {Point=P; ansMax=-inf; GetMax(rt); return ansMax;}
    int QueryMin(PointNode P) {Point=P; ansMin=inf; GetMin(rt); return ansMin;}
}KDTree;
int main()
{
    n=read();
    for (int x,y,i=1; i<=n; i++) x=read(),y=read(),p[i].d[0]=x,p[i].d[1]=y;
    for (int i=0; i<=1; i++) p[0].maxx[i]=-inf,p[0].minn[i]=inf;
    KDTree.rt=KDTree.BuildTree(1,n,1);
    ans=inf;
    for (int i=1; i<=n; i++)
        {
            int minn=KDTree.QueryMin(p[i]),maxx=KDTree.QueryMax(p[i]);
            ans=min(ans,maxx-minn);
        }
    printf("%d\n",ans);
    return 0;
}
时间: 2024-12-08 13:45:53

【BZOJ-1941】Hide and Seek KD-Tree的相关文章

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

Time Limit: 16 Sec  Memory Limit: 162 MBSubmit: 1712  Solved: 932[Submit][Status][Discuss] Description 小猪iPig在PKU刚上完了无聊的猪性代数课,天资聪慧的iPig被这门对他来说无比简单的课弄得非常寂寞,为了消除寂寞感,他决定和他的好朋友giPi(鸡皮)玩一个更加寂寞的游戏---捉迷藏. 但是,他们觉得,玩普通的捉迷藏没什么意思,还是不够寂寞,于是,他们决定玩寂寞无比的螃蟹版捉迷藏,顾名思义

bzoj:1941: [Sdoi2010]Hide and Seek

1941: [Sdoi2010]Hide and Seek Time Limit: 16 Sec  Memory Limit: 162 MBSubmit: 531  Solved: 295[Submit][Status][Discuss] Description 小猪iPig在PKU刚上完了无聊的猪性代数课,天资聪慧的iPig被这门对他来说无比简单的课弄得非常寂寞,为了消除寂寞感,他决定和他的好朋友giPi(鸡皮)玩一个更加寂寞的游戏---捉迷藏. 但是,他们觉得,玩普通的捉迷藏没什么意思,还是

K-D树:bzoj 1941: [Sdoi2010]Hide and Seek (板子)

1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define ls(x) a[x].l 6 #define rs(x) a[x].r 7 using namespace std; 8 const int N=500066; 9 int abss(int x){return x<0?-x:x;} 10 int maxn(int a,i

BZOJ 1941 Sdoi2010 Hide and Seek K-Dimensional-Tree

题目大意:给定平面上的n个点,定义距离为曼哈顿距离,求一个点到其他所有点的最大距离与最小距离之差最小 KDTree--这东西好神啊 注意计算最小距离的时候不能把自己也算进去= = #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 500500 #define INF 0x3f3f3f3f using namespace std; st

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

KD-Tree 一开始看错题了 其实是:给定n个点,从中找一个点,使得其他所有点到它距离的最大值与最小值之差最小. 利用KD-Tree暴力求出每个点的答案(找离它最近的点以及最远的点(当然只关心距离)) 然后……两个过程分开写…… 注意一下最近的点的距离不能是0(然而我一开始用 if (o==tmp) return INF; 就WA了……)(这里o是当前搜索到的点,tmp是枚举的起始点) 1 /***************************************************

【BZOJ 2820】 YY的GCD

2820: YY的GCD Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 807  Solved: 404 [Submit][Status] Description 神犇YY虐完数论后给傻×kAc出了一题 给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对 kAc这种傻×必然不会了,于是向你来请教-- 多组输入 Input 第一行一个整数T 表述数据组数 接下来T行,每行两个正整数,表示

【BZOJ 1854】 [Scoi2010]游戏

1854: [Scoi2010]游戏 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 2609  Solved: 931 [Submit][Status] Description lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备最多只能使用一次. 游戏进行到最后,lxhgww遇到了终极boss,这个终极bos

【BZOJ 1036】【ZJOI 2008】树的统计

此题为树链剖分的裸题. 代码如下,使用常用的轻重链剖分. /************************************************************** Problem: 1036 User: Evensgn Language: C++ Result: Accepted Time:2468 ms Memory:5772 kb ****************************************************************/ #inc

【BZOJ 1150】 1150: [CTSC2007]数据备份Backup (贪心+优先队列)

1150: [CTSC2007]数据备份Backup Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏的乐趣.已知办公 楼都位于同一条街上.你决定给这些办公楼配对(两个一组).每一对办公楼可以通过在这两个建筑物之间铺设网 络电缆使得它们可以互相备份.然而,网络电缆的费用很高.当地电信公司仅能为你提供 K 条网络电缆,这意味 着你仅