码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ-1941】Hide and Seek KD-Tree

时间:2016-05-27 08:19:25      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:

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; }

 

【BZOJ-1941】Hide and Seek KD-Tree

标签:

原文地址:http://www.cnblogs.com/DaD3zZ-Beyonder/p/5533319.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!