• 【bzoj1941】[Sdoi2010]Hide and Seek KD-tree


    题目描述

    小猪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的问题。

    输入

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

    输出

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

    样例输入

    4
    0 0
    1 0
    0 1
    1 1

    样例输出

    1


    题解

    KD-tree

    如果我们已经知道了一个固定的点,那么很容易求出距离它最远和最近的点。

    于是我们可以枚举已知的点,使用KD-tree求出与一个点距离最近和最远(好像可以贪心)的点。

    其中求最远的估价函数和最近点稍有区别,自己yy一下就好。

    注意求最近点时要忽略相同的点。

    #include <cstdio>
    #include <algorithm>
    #define N 1000010
    #define inf 0x7fffffff
    using namespace std;
    struct data
    {
        int p[2] , minn[2] , maxn[2] , c[2];
    }a[N];
    int d , root , ans;
    bool cmp(data a , data b)
    {
        return a.p[d] == b.p[d] ? a.p[d ^ 1] < b.p[d ^ 1] : a.p[d] < b.p[d];
    }
    void pushup(int k , int s)
    {
        a[k].minn[0] = min(a[k].minn[0] , a[s].minn[0]);
        a[k].minn[1] = min(a[k].minn[1] , a[s].minn[1]);
        a[k].maxn[0] = max(a[k].maxn[0] , a[s].maxn[0]);
        a[k].maxn[1] = max(a[k].maxn[1] , a[s].maxn[1]);
    }
    int build(int l , int r , int now)
    {
        int mid = (l + r) >> 1;
        d = now , nth_element(a + l , a + mid , a + r + 1 , cmp);
        a[mid].minn[0] = a[mid].maxn[0] = a[mid].p[0];
        a[mid].minn[1] = a[mid].maxn[1] = a[mid].p[1];
        if(l < mid) a[mid].c[0] = build(l , mid - 1 , now ^ 1) , pushup(mid , a[mid].c[0]);
        if(r > mid) a[mid].c[1] = build(mid + 1 , r , now ^ 1) , pushup(mid , a[mid].c[1]);
        return mid;
    }
    int getmin(int k , int x)
    {
        int ret = 0;
        if(a[x].p[0] < a[k].minn[0]) ret += a[k].minn[0] - a[x].p[0];
        if(a[x].p[0] > a[k].maxn[0]) ret += a[x].p[0] - a[k].maxn[0];
        if(a[x].p[1] < a[k].minn[1]) ret += a[k].minn[1] - a[x].p[1];
        if(a[x].p[1] > a[k].maxn[1]) ret += a[x].p[1] - a[k].maxn[1];
        return ret;
    }
    int getmax(int k , int x)
    {
        return max(abs(a[k].maxn[0] - a[x].p[0]) , abs(a[k].minn[0] - a[x].p[0])) + max(abs(a[k].maxn[1] - a[x].p[1]) , abs(a[k].minn[1] - a[x].p[1]));
    }
    void querymin(int k , int x)
    {
    	int dn = abs(a[k].p[0] - a[x].p[0]) + abs(a[k].p[1] - a[x].p[1]) , dl = inf , dr = inf;
    	if(dn && dn < ans) ans = dn;
    	if(a[k].c[0]) dl = getmin(a[k].c[0] , x);
    	if(a[k].c[1]) dr = getmin(a[k].c[1] , x);
    	if(dl < dr)
    	{
    		if(dl < ans) querymin(a[k].c[0] , x);
    		if(dr < ans) querymin(a[k].c[1] , x);
    	}
    	else
    	{
    		if(dr < ans) querymin(a[k].c[1] , x);
    		if(dl < ans) querymin(a[k].c[0] , x);
    	}
    }
    void querymax(int k , int x)
    {
    	int dn = abs(a[k].p[0] - a[x].p[0]) + abs(a[k].p[1] - a[x].p[1]) , dl = 0 , dr = 0;
    	if(dn > ans) ans = dn;
    	if(a[k].c[0]) dl = getmax(a[k].c[0] , x);
    	if(a[k].c[1]) dr = getmax(a[k].c[1] , x);
    	if(dl > dr)
    	{
    		if(dl > ans) querymax(a[k].c[0] , x);
    		if(dr > ans) querymax(a[k].c[1] , x);
    	}
    	else
    	{
    		if(dr > ans) querymax(a[k].c[1] , x);
    		if(dl > ans) querymax(a[k].c[0] , x);
    	}
    }
    int main()
    {
        int n , ret = inf , tmp , i;
        scanf("%d" , &n);
        for(i = 1 ; i <= n ; i ++ ) scanf("%d%d" , &a[i].p[0] , &a[i].p[1]);
        root = build(1 , n , 0);
        for(i = 1 ; i <= n ; i ++ )
    		ans = inf , querymin(root , i) , tmp = ans , ans = 0 , querymax(root , i) , ret = min(ret , ans - tmp);
        printf("%d
    " , ret);
        return 0;
    }
    

     

  • 相关阅读:
    AGC015E Mr.Aoki Incubator
    luogu P3520 [POI2011]SMI-Garbage
    442.Find All Duplicates in an Array
    SICP_2.61-2.62
    sicp_2.59-2.60
    SICP_2.58
    SICP_2.56-2.57
    SICP_2.53-2.55
    SICP_2.52-2.53
    SICP_2.50-2.51
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7102298.html
Copyright © 2020-2023  润新知