[SDOI2010]捉迷藏(线段树)

[SDOI2010]捉迷藏(luogu)

Solution

根据数据范围,大概需要O(nlogn)的算法,考虑数据结构

对于一个点(xi,yi)来说,其他点到它的距离为|xi-x|+|yi-y|

可以分为四种情况

  • xi>=x && yi>=y:|xi-x|+|yi-y|=xi-x+yi-y
  • xi>=x && yi<y: |xi-x|+|yi-y|=xi-x+y-yi
  • xi<=x && yi>=y:|xi-x|+|yi-y|=x-xi+yi-y
  • xi<=x && yi<y: |xi-x|+|yi-y|=x-xi+y-yi

发现每个式子都有确定的一部分和不确定的一部分

于是离散 y ,按 x 从小到大排序,用一个数据结构维护最小值和最大值

 

Code

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e5+10;
struct node
{
    int x,y,re;
    bool operator <(const node &o)const
    {
        return x<o.x;
    }
}a[N],d[N];
struct mode
{
    int lc,rc,l,r;
    int mi,ma;
}f[N*2];
int cnt,n,mi[N],ma[N],rt,tot;
void build(int &g,int l,int r)
{
    g=++tot;
    f[g].l=l,f[g].r=r;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(f[g].lc,l,mid);
    build(f[g].rc,mid+1,r);
}
int get_mi(int g,int l,int r)
{
    if(f[g].l>=l && f[g].r<=r)
        return f[g].mi;
    int mid=(f[g].l+f[g].r)>>1;
    if(r<=mid) return get_mi(f[g].lc,l,r);
    else if(l>mid) return get_mi(f[g].rc,l,r);
    else return min(get_mi(f[g].lc,l,mid),get_mi(f[g].rc,mid+1,r));
}
int get_ma(int g,int l,int r)
{
    if(f[g].l>=l && f[g].r<=r)
        return f[g].ma;
    int mid=(f[g].l+f[g].r)>>1;
    if(r<=mid) return get_ma(f[g].lc,l,r);
    else if(l>mid) return get_ma(f[g].rc,l,r);
    else return max(get_ma(f[g].lc,l,mid),get_ma(f[g].rc,mid+1,r));
}
void push_up(int g)
{
    int lc=f[g].lc,rc=f[g].rc;
    f[g].mi=min(f[lc].mi,f[rc].mi);
    f[g].ma=max(f[lc].ma,f[rc].ma);
}
void add(int g,int x,int k)
{
    if(f[g].l==f[g].r)
    {
        f[g].mi=min(f[g].mi,k);
        f[g].ma=max(f[g].ma,k);
        return ;
    }
    int mid=(f[g].l+f[g].r)>>1;
    if(x<=mid) add(f[g].lc,x,k);
    else add(f[g].rc,x,k);
    push_up(g);
}
void clear()
{
    for(int i=1;i<=tot;i++) f[i].mi=999999999,f[i].ma=-999999999;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        mi[i]=999999999,ma[i]=-999999999;
        scanf("%d%d",&d[i].x,&d[i].y);
        d[i].re=d[i].y;
        a[i]=(node){d[i].y,i,0};
    }
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++)
    {
        if(i==1 || a[i].x!=a[i-1].x) cnt++;
        d[a[i].y].y=cnt;
    }
    sort(d+1,d+1+n);
    //x<xi: (1)y<=yi xi-x+yi-y -x-y (2)y>yi xi-x+y-yi -x+y
    build(rt,1,cnt);
    clear();
    for(int i=1;i<=n;i++)
    {
        mi[i]=min(mi[i],d[i].x+d[i].re+get_mi(rt,1,d[i].y));
        ma[i]=max(ma[i],d[i].x+d[i].re+get_ma(rt,1,d[i].y));
        add(rt,d[i].y,-d[i].x-d[i].re);
    }
    clear();
    for(int i=1;i<=n;i++)
    {
        add(rt,d[i].y,-d[i].x+d[i].re);
        if(d[i].y==cnt) continue;
        mi[i]=min(mi[i],d[i].x-d[i].re+get_mi(rt,d[i].y+1,cnt));
        ma[i]=max(ma[i],d[i].x-d[i].re+get_ma(rt,d[i].y+1,cnt));
    }
    clear();
    //x>xi: (1)y>=yi x-xi+y-yi x+y  (2)y<yi x-xi+yi-y x-y
    for(int i=n;i;i--)
    {
        mi[i]=min(mi[i],-d[i].x-d[i].re+get_mi(rt,d[i].y,cnt));
        ma[i]=max(ma[i],-d[i].x-d[i].re+get_ma(rt,d[i].y,cnt));
        add(rt,d[i].y,d[i].x+d[i].re);
    }
    clear();
    for(int i=n;i;i--)
    {
        add(rt,d[i].y,d[i].x-d[i].re);
        if(d[i].y==1) continue;
        mi[i]=min(mi[i],-d[i].x+d[i].re+get_mi(rt,1,d[i].y-1));
        ma[i]=max(ma[i],-d[i].x+d[i].re+get_ma(rt,1,d[i].y-1));
    }
    int ans=999999999;
    for(int i=1;i<=n;i++) ans=min(ans,ma[i]-mi[i]);
    printf("%d\n",ans);
    return 0;
}                    
  • xi>=x && yi>=y:|xi-x|+|yi-y|=xi-x+yi-y

猜你喜欢

转载自www.cnblogs.com/hsez-cyx/p/12446634.html
今日推荐