Mummy Madness

Mummy Madness

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

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

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

你最长可以坚持到什么时刻不被木乃伊抓住?若你可以永远不被抓住,输出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=(ans2+1)2

然后这题就做完了

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

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

然后这题就做完了

话说这题怎么做应该是 O(TNlog2N) 的,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 @   liuboom  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示