Mummy Madness

Mummy Madness

你打开了一个埃及古墓,木乃伊们从几千年的沉睡中惊醒,变得十分暴躁。

沙漠看做一个无限大的网格,你在\((0,0)\)格子中,\(n(n \leq 10^5)\)只木乃伊分布在不同的格子中,不会有木乃伊初始在\((0,0)\),允许多只木乃伊同一时刻处于同一格子(坐标的绝对值小于等于\(10^6\))。

每一个时刻,你可以向周围的八个方向任意移动一格,或者保持不动。然后所有木乃伊会向着离你欧几里得距离最近的方向移动一格。

你最长可以坚持到什么时刻不被木乃伊抓住?若你可以永远不被抓住,输出never。

Solution

题目二次翻译:
给定平面上n个点,假设当前答案为ans
对每个点构造一个(x-ans,y-ans)-(x+ans,y+ans)的正方形
如果当前构造的所有矩形的并能将(-ans,-ans)-(ans,ans)
全部包含,则称当前答案可行,最小化ans

对于每一个矩形,将其端点
(x-ans,y-ans)->(max(x-ans,-ans),max(y-ans,-ans))
(x+ans,y+ans)->(min(x+ans,ans),min(y+ans,ans))
然后我们用扫描线维护矩形面积并
当前答案可行等价于 $ S=(ans*2+1)^2 $

然后这题就做完了

注意:代码中由于扫描线维护的区间左闭右开,所以在第二个端点处的x,y均需要++

然后就是 臭名昭著 喜闻乐见的离散化环节了

然后这题就做完了

话说这题怎么做应该是 \(O(T*N*log^2 N)\) 的,luogu上给20s
LD只给8s???

Code:

#include <bits/stdc++.h>
#define ls (x<<1)
#define rs (x<<1|1)
const int N=1e5+5;
using namespace std;
int n,T;
struct Tree{
    int l,r,cnt,len;
}t[N<<2];
struct Line{
    int l,r,y,val;
    bool operator <(const Line &L)const{
        return y<L.y;
    }
};
int x[N],y[N];
vector<int> a;
vector<Line> Q;
void pushup(int x)
{
    t[x].len=0;
    if(t[x].cnt)
    {
        t[x].len=a[t[x].r]-a[t[x].l];
    }
    else if(t[x].l+1<t[x].r)
    t[x].len=t[ls].len+t[rs].len;
}
void build(int x,int l,int r)
{
    t[x].len=t[x].cnt=0;
    t[x].l=l,t[x].r=r;
    if(l+1>=r)return ;
    int mid=l+r>>1;
    build(ls,l,mid);
    build(rs,mid,r);
}
void upd(int x,int ll,int rr,int val)
{
    if(ll<=t[x].l&&t[x].r<=rr)
    {
        t[x].cnt+=val;
        pushup(x);
        return ;
    }
    int mid=t[x].l+t[x].r>>1;
    if(ll<mid)upd(ls,ll,rr,val);
    if(mid<rr)upd(rs,ll,rr,val);
    pushup(x);
}
bool check(int mid)
{
    long long sum=0,range=mid;
    Q.clear();
    a.clear();
    for(int i=1,x1,x2,y1,y2;i<=n;i++)
    {
        x1=max(-range,x[i]-range),x2=min(range+1,x[i]+range+1);
        y1=max(-range,y[i]-range),y2=min(range+1,y[i]+range+1);
        //cout<<x1<<" "<<x2<<"--"<<y1<<" "<<y2<<"\n";
        if(x1<x2&&y1<y2)
        {
            Q.push_back((Line){x1,x2,y1,1});
            Q.push_back((Line){x1,x2,y2,-1});
            a.push_back(x1);
            a.push_back(x2);
        }

    }
    sort(Q.begin(),Q.end());
    sort(a.begin(),a.end());
    a.erase(unique(a.begin(),a.end()),a.end());
    int tot=a.size(),sz=Q.size();
    build(1,0,tot-1);
    for(int i=0;i<sz;i++)
    {
        int L=lower_bound(a.begin(),a.end(),Q[i].l)-a.begin(),R=lower_bound(a.begin(),a.end(),Q[i].r)-a.begin();
        upd(1,L,R,Q[i].val);
        while(i<sz-1&&Q[i+1].y==Q[i].y)
        {
            i++;
            L=lower_bound(a.begin(),a.end(),Q[i].l)-a.begin(),R=lower_bound(a.begin(),a.end(),Q[i].r)-a.begin();
            upd(1,L,R,Q[i].val);
        }
        if(i<sz-1)
        {
            sum+=1ll*(Q[i+1].y-Q[i].y)*t[1].len;
            //cout<<"high: "<<Q[i+1].y<<"-"<<Q[i].y<<" \nlen:"<<t[1].len<<"\n";
        }
    }
    range=range<<1|1;
    //cout<<"range:"<<range<<" "<<sum<<"="<<range*range<<"\n";
    return sum==range*range;
}
void work()
{
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
    }
    int l=1,r=1e6,ans=-1;
    while(l<=r)
    {
        int mid=l+r>>1;
        if(check(mid))
        {
            ans=mid;
            r=mid-1;
        }
        else
        {
            l=mid+1;
        }
    }
    printf("Case %d: ",++T);
    if(~ans)
    {
        printf("%d\n",ans);
    }
    else
    {
        printf("never\n");
    }

}
int main()
{
    //freopen("madness.in","r",stdin);
    //freopen("madness.out","w",stdout);
    while(cin>>n)
    {
        if(n==-1)break;
        work();
    }
    return 0;
}
posted @ 2024-12-06 11:53  liuboom  阅读(16)  评论(0)    收藏  举报