• 【BZOJ1941】[Sdoi2010]Hide and Seek KDtree


    【BZOJ1941】[Sdoi2010]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

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

    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

    题解:KDtree裸题+1,一开始以为距离最远的可以直接贪心来搞,结果WA了无数次~

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define rep for(int i=0;i<=1;i++)
    using namespace std;
    int n,m,root,D,maxx,minn,ans;
    int kx[]={1,-1,1,-1},ky[]={1,1,-1,-1},dm[5];
    struct kd
    {
        int v[2],sn[2],sm[2],ls,rs;
        kd (int a,int b){ls=rs=0,v[0]=sn[0]=sm[0]=a,v[1]=sn[1]=sm[1]=b;}
        kd (){}
    };
    kd t[500010];
    bool cmp(kd a,kd b)
    {
        if(a.v[D]==b.v[D])  return a.v[D^1]<b.v[D^1];
        return a.v[D]<b.v[D];
    }
    int rd()
    {
        int ret=0,f=1;  char gc=getchar();
        while(gc<'0'||gc>'9') {if(gc=='-')f=-f;   gc=getchar();}
        while(gc>='0'&&gc<='9')   ret=ret*10+gc-'0',gc=getchar();
        return ret*f;
    }
    void pushup(int x,int y)
    {
        rep t[x].sn[i]=min(t[x].sn[i],t[y].sn[i]),t[x].sm[i]=max(t[x].sm[i],t[y].sm[i]);
    }
    int build(int l,int r,int d)
    {
        if(l>r)  return 0;
        int mid=l+r>>1;
        D=d;
        nth_element(t+l,t+mid,t+r+1,cmp);
        t[mid].ls=build(l,mid-1,d^1),t[mid].rs=build(mid+1,r,d^1);
        if(t[mid].ls)   pushup(mid,t[mid].ls);
        if(t[mid].rs)   pushup(mid,t[mid].rs);
        return mid;
    }
    int getmin(int x,int y)
    {
        int ret=0;
        rep ret+=max(t[y].v[i]-t[x].sm[i],0)+max(t[x].sn[i]-t[y].v[i],0);
        return ret;
    }
    int getmax(int x,int y)
    {
    	int ret=0;
    	rep	ret+=max(abs(t[x].sm[i]-t[y].v[i]),abs(t[x].sn[i]-t[y].v[i]));
    	return ret;
    }
    void qmin(int x,int y)
    {
        if(!x||getmin(x,y)>=minn)    return ;
        if(x!=y)    minn=min(minn,abs(t[x].v[0]-t[y].v[0])+abs(t[x].v[1]-t[y].v[1]));
        if(t[x].ls*t[x].rs==0)  qmin(t[x].ls^t[x].rs,y);
        else    if(getmin(t[x].ls,y)<getmin(t[x].rs,y))  qmin(t[x].ls,y),qmin(t[x].rs,y);
        else    qmin(t[x].rs,y),qmin(t[x].ls,y);
    }
    void qmax(int x,int y)
    {
    	if(!x||getmax(x,y)<=maxx)	return ;
    	if(x!=y)	maxx=max(maxx,abs(t[x].v[0]-t[y].v[0])+abs(t[x].v[1]-t[y].v[1]));
    	if(t[x].ls*t[x].rs==0)	qmax(t[x].ls^t[x].rs,y);
    	else	if(getmax(t[x].ls,y)>getmax(t[x].rs,y))	qmax(t[x].ls,y),qmax(t[x].rs,y);
    	else	qmax(t[x].rs,y),qmax(t[x].ls,y);
    }
    int main()
    {
        n=rd();
        int i,j,a,b;
        dm[0]=dm[1]=dm[2]=dm[3]=1;
        for(i=1;i<=n;i++)
        {
            a=rd(),b=rd(),t[i]=kd(a,b);
            for(j=0;j<4;j++) if(a*kx[j]+b*ky[j]<t[dm[j]].v[0]*kx[j]+t[dm[j]].v[1]*ky[j])  dm[j]=i;
        }
        root=build(1,n,0),ans=1<<30;
        for(i=1;i<=n;i++)
        {
            maxx=0,minn=1<<30;
            qmax(root,i),qmin(root,i);
            ans=min(ans,maxx-minn);
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    python文件打开方式详解——a、a+、r+、w+、rb、rt区别
    io.UnsupportedOperation: can't do nonzero cur-relative seeks”错误
    端口三种模式:access,hybrid,trunk
    水仙花数
    maktrans和translate详解
    实战NFS服务搭建与配置
    except 配合 shell实现公钥分发脚本
    linux系统免秘钥分发文件
    rsync + inotify 实现远程实时同步数据
    通过rsync实现全网数据备份检查脚本
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/6921213.html
Copyright © 2020-2023  润新知