zoukankan      html  css  js  c++  java
  • 【BZOJ1941】Hide and Seek(SDOI2010)-KD树

    测试地址:Hide and Seek
    做法:本题需要用到KD树。
    KD树是一种维护空间中点集的数据结构,构造方法网上应该有挺多讲解,这里就不赘述了,而这道题中求曼哈顿距离最大和最小是KD树的经典应用,一次查询的复杂度最好是O(logn),最坏是O(n),这样就可以通过此题了。
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int inf=1000000000;
    int n,rt,ansmax,ansmin,qryx,qryy,D;
    struct point
    {
        int d[2];
    }p[100010];
    struct node
    {
        int d[2],ch[2],x[2],y[2];
    }a[100010];
    
    bool operator < (point a,point b)
    {
        return a.d[D]==b.d[D]?a.d[D^1]<b.d[D^1]:a.d[D]<b.d[D];
    }
    
    void pushup(int no)
    {
        int lc=a[no].ch[0],rc=a[no].ch[1];
        if (lc)
        {
            a[no].x[0]=min(a[no].x[0],a[lc].x[0]);
            a[no].x[1]=max(a[no].x[1],a[lc].x[1]);
            a[no].y[0]=min(a[no].y[0],a[lc].y[0]);
            a[no].y[1]=max(a[no].y[1],a[lc].y[1]);
        }
        if (rc)
        {
            a[no].x[0]=min(a[no].x[0],a[rc].x[0]);
            a[no].x[1]=max(a[no].x[1],a[rc].x[1]);
            a[no].y[0]=min(a[no].y[0],a[rc].y[0]);
            a[no].y[1]=max(a[no].y[1],a[rc].y[1]);
        }
    }
    
    int buildtree(int l,int r,int f)
    {
        if (l>r) return 0;
        int mid=(l+r)>>1;
        D=f;
        nth_element(p+l,p+mid,p+r+1);
        a[mid].d[0]=a[mid].x[0]=a[mid].x[1]=p[mid].d[0];
        a[mid].d[1]=a[mid].y[0]=a[mid].y[1]=p[mid].d[1];
        a[mid].ch[0]=buildtree(l,mid-1,f^1);
        a[mid].ch[1]=buildtree(mid+1,r,f^1);
        pushup(mid);
        return mid;
    }
    
    int getmax(int no)
    {
        return max(qryx-a[no].x[0],a[no].x[1]-qryx)+max(qryy-a[no].y[0],a[no].y[1]-qryy);
    }
    
    int getmin(int no)
    {
        return max(a[no].x[0]-qryx,0)+max(qryx-a[no].x[1],0)+max(a[no].y[0]-qryy,0)+max(qryy-a[no].y[1],0);
    }
    
    void querymax(int v)
    {
        if (a[v].d[0]!=qryx||a[v].d[1]!=qryy)
            ansmax=max(ansmax,abs(qryx-a[v].d[0])+abs(qryy-a[v].d[1]));
        int dis[2]={-inf,-inf};
        if (a[v].ch[0]) dis[0]=max(dis[0],getmax(a[v].ch[0]));
        if (a[v].ch[1]) dis[1]=max(dis[1],getmax(a[v].ch[1]));
        bool t=(dis[0]<=dis[1]);
        if (dis[t]>ansmax) querymax(a[v].ch[t]);
        t^=1;
        if (dis[t]>ansmax) querymax(a[v].ch[t]);
    }
    
    void querymin(int v)
    {
        if (a[v].d[0]!=qryx||a[v].d[1]!=qryy)
            ansmin=min(ansmin,abs(qryx-a[v].d[0])+abs(qryy-a[v].d[1]));
        int dis[2]={inf,inf};
        if (a[v].ch[0]) dis[0]=min(dis[0],getmin(a[v].ch[0]));
        if (a[v].ch[1]) dis[1]=min(dis[1],getmin(a[v].ch[1]));
        bool t=(dis[0]>=dis[1]);
        if (dis[t]<ansmin) querymin(a[v].ch[t]);
        t^=1;
        if (dis[t]<ansmin) querymin(a[v].ch[t]);
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&p[i].d[0],&p[i].d[1]);
    
        rt=buildtree(1,n,0);
        int ans=inf;
        for(int i=1;i<=n;i++)
        {
            qryx=p[i].d[0],qryy=p[i].d[1];
            ansmax=-inf;
            querymax(rt);
            ansmin=inf;
            querymin(rt);
            ans=min(ans,ansmax-ansmin);
        }
        printf("%d",ans);
    
        return 0;
    }
  • 相关阅读:
    Google Kubernetes设计文档之服务篇-转
    基于kubernetes构建Docker集群管理详解-转
    Pass云Docker介绍
    Spring <context:annotation-config/> 解说
    webapp开发需要注意的浏览器内核知识
    koala编译scss文件时不支持中文字体的解决方案
    CSS3硬件加速需要注意的事项
    ios客户端快速滚动和回弹效果的实现
    mui禁止滚动条和禁止滚动
    苹果端禁用左右滑动屏幕返回上级页面
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793424.html
Copyright © 2011-2022 走看看