【BZOJ 3958】 3958: [WF2011]Mummy Madness (二分+扫描线、线段树)
3958: [WF2011]Mummy Madness
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 96 Solved: 41Description
在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓。不幸的是,你打开了坟墓之后,才发现这是一个坏主意:突然之间,原本空无一物的沙漠上已经爬满了暴躁的木乃伊。(如果你也沉睡几千年而突然被惊醒,你也会变得如此暴躁的。)(幸运的是,当你做完这道题的时候,你醒来了,发现你在弗罗里达的酒店里。那些木乃伊只是一场梦。)面对这一大堆疯狂的木乃伊,你唯一的机会就是试图在他们抓到你之前逃跑。问题是:假如你与木乃伊永不疲倦,那么经过多长时间你会被木乃伊抓到?我们把沙漠看成一个正方形的网格,你与木乃伊轮流移动(你走出第一步)。轮到你时,你可以移动到相邻的8个格子之一,或者站着不动。轮到木乃伊时,每个木乃伊会移动到其相邻的格子之一,使得他与你的欧几里得距离尽量小(假设你与木乃伊都站在格子的中心位置)。允许多个木乃伊同时占据同一个格子。在每个单位时间内,你先做出移动,然后木乃伊做出移动。如果你与任何一个木乃伊站在同一位置,你会被抓住。当然,你试图尽量长时间避免被抓住。经过多少单位时间你会被抓住呢?下图描述了你被4个木乃伊追逐的例子。H代表你的初始位置,而M代表木乃伊的初始位置。以你的初始位置为原点,则经过4个单位时间后,你被初始位置为(3,4)的木乃伊抓住。Input
输入文件包含若干组数据。每组数据的第一行为一个数n(0≤n≤10^5),表示沙漠中木乃伊的个数。接下来n行,每行两个整数x y,表示初始时在(x,y)有一个木乃伊。x,y的绝对值均不超过10^6。你的初始位置是(0,0),保证一开始这里没有木乃伊。输入文件以一行-1结束。Output
对于每组测试数据,输出一行,包括它的编号和被抓住经过的最长时间(即你做出决策的次数);或输出"never",如果你有办法永远不被抓住。请以样例输出的格式输出数据。Sample Input
4
-3 5
3 4
-6 -2
1 -5
1
0 -1
-1Sample Output
Case 1: 4
Case 2: neverHINT
对于100%的数据,n≤10^5Source
【分析】
我不会做。。膜奥爷爷。。
二分【显然可以】走多少步,然后把人和木乃伊能走的范围【是矩形】画出来,然后如果木乃伊们能走的范围完全覆盖了人能走的范围,那么就会被赶尽杀绝了!!
然后就线段树做扫描线。。具体看之前的博客:http://www.cnblogs.com/Konjakmoyu/p/6050343.html
wohenshuai说得对,不要随便离散化【但是我还是离散化了】,不然很容易错。。
然后,只做询问的区间,不然很容易T【我已经T了3、4遍了,卡评测】
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 100010 8 9 int mymin(int x,int y) {return x<y?x:y;} 10 int mymax(int x,int y) {return x>y?x:y;} 11 12 struct node{int x,y;}t[Maxn]; 13 struct hp{int l,r,h,f;}w[Maxn*6]; 14 struct lsh{int x,id;}ls[Maxn*6]; 15 bool cmp(lsh x,lsh y) {return x.x<y.x;} 16 bool cmp2(hp x,hp y) {return (x.h==y.h)?(x.f>y.f):(x.h<y.h);} 17 int n; 18 19 struct nnode 20 { 21 int l,r,lc,rc,cnt; 22 bool p; 23 }tr[Maxn*20]; 24 25 int tot; 26 int build(int l,int r) 27 { 28 int x=++tot; 29 tr[x].l=l;tr[x].r=r; 30 tr[x].cnt=0;tr[x].p=0; 31 if(l!=r) 32 { 33 int mid=(l+r)>>1; 34 tr[x].lc=build(l,mid); 35 tr[x].rc=build(mid+1,r); 36 } 37 else tr[x].lc=tr[x].rc=0; 38 return x; 39 } 40 41 void upd(int x) 42 { 43 if(tr[tr[x].lc].p&&tr[tr[x].rc].p) tr[x].p=1; 44 else if(tr[x].cnt>0) tr[x].p=1; 45 else tr[x].p=0; 46 } 47 48 void change(int x,int l,int r,int y) 49 { 50 if(tr[x].l==l&&tr[x].r==r) 51 { 52 tr[x].cnt+=y; 53 upd(x); 54 return; 55 } 56 int mid=(tr[x].l+tr[x].r)>>1; 57 if(r<=mid) change(tr[x].lc,l,r,y); 58 else if(l>mid) change(tr[x].rc,l,r,y); 59 else 60 { 61 change(tr[x].lc,l,mid,y); 62 change(tr[x].rc,mid+1,r,y); 63 } 64 upd(x); 65 } 66 67 int query(int x,int l,int r) 68 { 69 if(tr[x].p) return 1; 70 if(tr[x].l==l&&tr[x].r==r) return tr[x].p; 71 int mid=(tr[x].l+tr[x].r)>>1; 72 if(r<=mid) return query(tr[x].lc,l,r); 73 else if(l>mid) return query(tr[x].rc,l,r); 74 else return (query(tr[x].lc,l,mid)&&query(tr[x].rc,mid+1,r)); 75 } 76 77 bool check(int nw) 78 { 79 w[1].l=-nw;w[1].r=nw;w[1].h=-nw;w[1].f=-3; 80 w[2].l=-nw;w[2].r=nw;w[2].h=nw;w[2].f=-2; 81 int wl=2; 82 for(int i=1;i<=n;i++) 83 { 84 if(t[i].y+nw<-nw||t[i].y-nw>nw) continue; 85 if(t[i].x+nw<-nw||t[i].x-nw>nw) continue; 86 w[++wl].l=mymax(-nw,t[i].x-nw);w[wl].r=mymin(t[i].x+nw,nw);w[wl].h=t[i].y-nw;w[wl].f=1; 87 if(t[i].y+nw<=nw) {w[++wl].l=mymax(t[i].x-nw,-nw);w[wl].r=mymin(t[i].x+nw,nw);w[wl].h=t[i].y+nw+1;w[wl].f=-1;} 88 } 89 int sl=0; 90 for(int i=1;i<=wl;i++) {ls[++sl].x=w[i].l,ls[sl].id=i;ls[++sl].x=w[i].r;ls[sl].id=-i;} 91 sort(ls+1,ls+sl+1,cmp); 92 int p=1; 93 if(ls[1].id>0) w[ls[1].id].l=1; 94 else w[-ls[1].id].r=1; 95 for(int i=2;i<=sl;i++) 96 { 97 if(ls[i].x!=ls[i-1].x) 98 { 99 // p++; 100 if(ls[i].x-ls[i-1].x==1) p++; 101 else p+=2; 102 } 103 if(ls[i].id>0) w[ls[i].id].l=p; 104 else w[-ls[i].id].r=p; 105 } 106 sort(w+1,w+1+wl,cmp2); 107 tot=0; 108 build(1,p); 109 bool ok=1; 110 int asl=-1,asr; 111 for(int i=1;i<=wl;i++) 112 { 113 if(w[i].f==-3) asl=w[i].l,asr=w[i].r; 114 if(w[i].f!=-2&&w[i].f!=-3) change(1,w[i].l,w[i].r,w[i].f); 115 if(asl!=-1&&!tr[1].p) {ok=0;break;} 116 if(w[i].f==-2) break; 117 } 118 return ok; 119 } 120 121 void ffind(int l,int r) 122 { 123 int ans=-1; 124 while(l<=r) 125 { 126 int mid=(l+r)>>1; 127 if(check(mid)) ans=mid,r=mid-1; 128 else l=mid+1; 129 } 130 if(ans==-1) printf("never\n"); 131 else printf("%d\n",ans); 132 } 133 134 int main() 135 { 136 int kase=0; 137 while(1) 138 { 139 scanf("%d",&n); 140 if(n==-1) break; 141 for(int i=1;i<=n;i++) scanf("%d%d",&t[i].x,&t[i].y); 142 printf("Case %d: ",++kase); 143 ffind(1,1000000); 144 } 145 return 0; 146 }
2017-03-28 19:21:43