题目分析
在T时刻,每一个木乃伊可能处于的位置,和你可能处于的位置,都是个正方形。如果木乃伊们的正方形将你的正方形完全覆盖,你无处落脚,必定死亡。
而T+1时刻,因为T时刻木乃伊可能在的每个格子的周围8个格子,此时都可能有木乃伊了,所以,不可能在T时刻没有你可以待的地方,T+1时刻就有了。因此,你无可落脚这个状态是单调的,可以二分。
二分答案,求出所有木乃伊的正方形和你的正方形的并(是个矩形),然后扫描线求出这些矩形的面积并,与你的正方形的面积比较,可知此时你能否活着。
代码
离散化太麻烦,我是用了动态开点线段树……
#include<bits/stdc++.h>
using namespace std;
#define RI register int
int read() {
int q=0,w=1;char ch=' ';
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') w=-1,ch=getchar();
while(ch>='0'&&ch<='9') q=q*10+ch-'0',ch=getchar();
return q*w;
}
typedef long long LL;
const int N=100005,M=2000000;
int n,kas,js,SZ,rt;
struct mummy{int x,y;}mu[N];
struct line{int x,l,r,op;}seg[N<<1];
struct node{int ls,rs;LL v,lz;}tr[N*40];
bool cmp(line l1,line l2) {return l1.x<l2.x;}
void up(int x,int s,int t) {
if(tr[x].lz) tr[x].v=t-s+1;
else if(s==t) tr[x].v=0;
else tr[x].v=tr[tr[x].ls].v+tr[tr[x].rs].v;
}
void ins(int l,int r,int s,int t,int &x,LL num) {
if(!x) x=++SZ,tr[x].v=tr[x].lz=tr[x].ls=tr[x].rs=0;
if(l<=s&&t<=r) {tr[x].lz+=num,up(x,s,t);return;}
int mid=(s+t)>>1;
if(l<=mid) ins(l,r,s,mid,tr[x].ls,num);
if(mid+1<=r) ins(l,r,mid+1,t,tr[x].rs,num);
up(x,s,t);
}
int check(int T) {
js=SZ=rt=0;LL orz=0;
for(RI i=1;i<=n;++i) {
int X1=max(-T,mu[i].x-T),X2=min(T,mu[i].x+T);
int Y1=max(-T,mu[i].y-T),Y2=min(T,mu[i].y+T);
if(X1>X2||Y1>Y2) continue;
seg[++js]=(line){X1,Y1,Y2,1},seg[++js]=(line){X2+1,Y1,Y2,-1};
}
sort(seg+1,seg+1+js,cmp);
for(RI i=1;i<=js;++i) {
if(i!=1) orz+=1LL*(seg[i].x-seg[i-1].x)*tr[rt].v;
ins(seg[i].l,seg[i].r,-M,M,rt,seg[i].op);
}
return orz>=1LL*(T+T+1)*(T+T+1);
}
int main()
{
while(1) {
n=read(),++kas;if(n==-1) break;
for(RI i=1;i<=n;++i) mu[i].x=read(),mu[i].y=read();
int l=1,r=1000000,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: ",kas);
if(ans==-1) puts("never");
else printf("%d\n",ans);
}
return 0;
}