bzoj1941 Hide and Seek

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

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

建立k-d树,枚举每个点查询最近点和最远点的曼哈顿距离。

单次查询最坏时间复杂度O(n0.5)但通常不会达到。

#include<cstdio>
#include<algorithm>
#define inf 2147483647
inline int abs(int x){return x>0?x:-x;}
inline int max(int x,int y){return x>y?x:y;}
inline int min(int x,int y){return x<y?x:y;}
inline void maxs(int&x,int y){if(x<y)x=y;}
inline void mins(int&x,int y){if(x>y)x=y;}
inline int max0(int x){return x>0?x:0;}
struct pos{
    int x,y;
};
struct node{
    int x1,y1,x2,y2;
    int xm,ym;
    int l,r;
    node():x1(inf),y1(inf),x2(-inf),y2(-inf){}
    inline void set(int x,int y){
        x1=x2=xm=x;
        y1=y2=ym=y;
    }
};
int dx=0;
bool operator<(pos a,pos b){
    if(dx)return a.x<b.x;
    return a.y<b.y;
}
node ns[500005];
pos ps[500005];
int np=1,n;
int X,Y,minv,maxv,ans(inf);
int build(int l,int r,int d=0){
    if(l==r)return 0;
    dx=d;
    int m=l+r>>1;
    node&w=ns[np++];
    std::nth_element(ps+l,ps+m,ps+r);
    w.set(ps[m].x,ps[m].y);
    d^=1;
    w.l=build(l,m,d);
    mins(w.x1,ns[w.l].x1);
    mins(w.y1,ns[w.l].y1);
    maxs(w.x2,ns[w.l].x2);
    maxs(w.y2,ns[w.l].y2);
    w.r=build(m+1,r,d);
    mins(w.x1,ns[w.r].x1);
    mins(w.y1,ns[w.r].y1);
    maxs(w.x2,ns[w.r].x2);
    maxs(w.y2,ns[w.r].y2);
    return &w-ns;
}
inline int maxd(int v){
    if(!v)return 0;
    node&w=ns[v];
    return max0(X-w.x1)+max0(w.x2-X)+max0(Y-w.y1)+max0(w.y2-Y);
}
inline int mind(int v){
    if(!v)return inf;
    node&w=ns[v];
    return max0(X-w.x2)+max0(w.x1-X)+max0(Y-w.y2)+max0(w.y1-Y);
}
void nt(int v=1){
    node&w=ns[v];
    int a=abs(X-w.xm)+abs(Y-w.ym);
    if(a)mins(minv,a);
    int ld=mind(w.l);
    int rd=mind(w.r);
    if(ld<rd){
        if(ld<minv)nt(w.l);
        if(rd<minv)nt(w.r);
    }else{
        if(rd<minv)nt(w.r);
        if(ld<minv)nt(w.l);
    }
}
void ft(int v=1){
    node&w=ns[v];
    int a=abs(X-w.xm)+abs(Y-w.ym);
    if(a)maxs(maxv,a);
    int ld=maxd(w.l);
    int rd=maxd(w.r);
    if(ld>rd){
        if(ld>maxv)ft(w.l);
        if(rd>maxv)ft(w.r);
    }else{
        if(rd>maxv)ft(w.r);
        if(ld>maxv)ft(w.l);
    }
}
inline int read(){
    char c=getchar();
    int x=0;
    while(c>‘9‘||c<‘0‘)c=getchar();
    while(c>=‘0‘&&c<=‘9‘)
    x=x*10+c-‘0‘,c=getchar();
    return x;
}
int main(){
    n=read();
    for(int i=0;i<n;i++)ps[i].x=read(),ps[i].y=read();
    build(0,n);
    for(int i=0;i<n;i++){
        X=ps[i].x;Y=ps[i].y;
        minv=inf;maxv=0;
        nt();
        ft();
        mins(ans,maxv-minv);
    }
    printf("%d",ans);
    return 0;
}
时间: 2024-10-23 12:11:05

bzoj1941 Hide and Seek的相关文章

【BZOJ-1941】Hide and Seek KD-Tree

1941: [Sdoi2010]Hide and Seek Time Limit: 16 Sec  Memory Limit: 162 MBSubmit: 830  Solved: 455[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(鸡皮)玩一个更加寂寞的游戏---捉迷藏. 但是,他们觉得,玩普通的捉迷藏没什么意思,还是

3402: [Usaco2009 Open]Hide and Seek 捉迷藏

3402: [Usaco2009 Open]Hide and Seek 捉迷藏 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 78  Solved: 64[Submit][Status] Description 贝茜在和约翰玩一个“捉迷藏”的游戏. 她正要找出所有适合她躲藏的安全牛棚.一共有N(2≤N≤20000)个牛棚,被编为1到N号.她知道约翰(捉牛者)从牛棚1出发.所有的牛棚由M(1≤M≤50000)条双向路连接,每条双向路连接两个不同的牛棚

BZOJ 3402: [Usaco2009 Open]Hide and Seek 捉迷藏

题目 3402: [Usaco2009 Open]Hide and Seek 捉迷藏 Time Limit: 3 Sec  Memory Limit: 128 MB Description 贝茜在和约翰玩一个“捉迷藏”的游戏. 她正要找出所有适合她躲藏的安全牛棚.一共有N(2≤N≤20000)个牛棚,被编为1到N号.她知道约翰(捉牛者)从牛棚1出发.所有的牛棚由M(1≤M≤50000)条双向路连接,每条双向路连接两个不同的牛棚.所有的牛棚都是相通的.贝茜认为同牛棚1距离最远的的牛棚是安全的.两个

洛谷 P2951 [USACO09OPEN]捉迷藏Hide and Seek

题目描述 Bessie is playing hide and seek (a game in which a number of players hide and a single player (the seeker) attempts to find them after which various penalties and rewards are assessed; much fun usually ensues). She is trying to figure out in whi

BZOJ3402: [Usaco2009 Open]Hide and Seek 捉迷藏

3402: [Usaco2009 Open]Hide and Seek 捉迷藏 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 51  Solved: 40[Submit][Status] Description 贝茜在和约翰玩一个“捉迷藏”的游戏. 她正要找出所有适合她躲藏的安全牛棚.一共有N(2≤N≤20000)个牛棚,被编为1到N号.她知道约翰(捉牛者)从牛棚1出发.所有的牛棚由M(1≤M≤50000)条双向路连接,每条双向路连接两个不同的牛棚

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

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

Luogu 2951 捉迷藏Hide and Seek

P2951 [USACO09OPEN]捉迷藏Hide and Seek 题目描述 Bessie is playing hide and seek (a game in which a number of players hide and a single player (the seeker) attempts to find them after which various penalties and rewards are assessed; much fun usually ensues)

【kd-tree】bzoj1941 [Sdoi2010]Hide and Seek

枚举每个点,计算离他最近的和最远的点. #include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define N 500001 #define INF 2147483647 #define KD 2//ά¶ÈÊý int qp[KD],disn,disx; int n,root; bool dn; struct Node { int minn[KD],maxx[KD],p[K