【BZOJ3958】[WF2011]Mummy Madness 二分+掃描線+線段樹
阿新 • • 發佈:2017-11-26
inpu 試圖 cpp 實現 truct highlight icp 永不 src
-3 5
3 4
-6 -2
1 -5
1
0 -1
-1
Case 2: never
【BZOJ3958】[WF2011]Mummy Madness
Description
在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
Sample Output
Case 1: 4Case 2: never
HINT
對於100%的數據,n≤10^5題解:容易想到二分答案mid,因為如果在mid時刻能抓到以後也一直是抓到的。在mid時刻,人可能到達的位置是一個正方形,每個木乃伊能到達的位置也是正方形,我們可以發現如果在mid時刻被抓了,當且僅當木乃伊的移動位置將人的移動位置完全覆蓋了。所以我們只需要判斷若幹個矩形的並是否能覆蓋給定矩形即可,用掃描線+線段樹可以實現。
但是本人從來沒寫過矩形並啊,這裏學習一發:
考慮標記永久化,我們對於線段樹上的每個節點維護cnt:區間中被覆蓋的位置個數,sum:當前區間被覆蓋了幾層。其中cnt相當於值,可以pushup,而sum相當於標記,但不能pushdown。如果一個區間的sum>0,我們令cnt=r-l+1;否則cnt=cnt[lson]+cnt[rson]。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define lson x<<1 #define rson x<<1|1 using namespace std; const int maxn=100010; int n,tot; struct node { int l,r,x,k; node() {} node(int a,int b,int c,int d) {l=a,r=b,x=c,k=d;} }p[maxn<<1]; int x[maxn],y[maxn],s1[maxn*80],s[maxn*80]; bool tc[maxn*80]; bool cmp(const node &a,const node &b) { return a.x<b.x; } void updata(int l,int r,int x,int a,int b,int c) { if(l!=r&&tc[x]) tc[lson]=tc[rson]=1,s1[lson]=s1[rson]=s[lson]=s[rson]=tc[x]=0; if(a<=l&&r<=b) { s[x]+=c; if(s[x]) s1[x]=r-l+1; else if(l!=r) s1[x]=s1[lson]+s1[rson]; else s1[x]=0; return ; } int mid=(l+r)>>1; if(a<=mid) updata(l,mid,lson,a,b,c); if(b>mid) updata(mid+1,r,rson,a,b,c); if(s[x]) s1[x]=r-l+1; else if(l!=r) s1[x]=s1[lson]+s1[rson]; else s1[x]=0; } inline bool check(int mid) { int i; tot=0; for(i=1;i<=n;i++) { if(x[i]+mid<-mid||x[i]-mid>mid||y[i]+mid<-mid||y[i]-mid>mid) continue; p[++tot]=node(max(-mid,y[i]-mid),min(mid,y[i]+mid),max(-mid,x[i]-mid),1); p[++tot]=node(max(-mid,y[i]-mid),min(mid,y[i]+mid),min(mid+1,x[i]+mid+1),-1); } sort(p+1,p+tot+1,cmp); tc[1]=1,s[1]=s1[1]=0; p[0].x=-mid,p[tot+1]=node(0,0,mid+1,0); for(i=1;i<=tot+1;i++) { if(p[i].x>p[i-1].x&&s1[1]<2*mid+1) return 1; updata(-mid,mid,1,p[i].l,p[i].r,p[i].k); } return 0; } inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘) f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+(gc^‘0‘),gc=getchar(); return ret*f; } int main() { for(int cas=1;;cas++) { n=rd(); if(n==-1) return 0; int i,l=0,r=1000001,mid; for(i=1;i<=n;i++) x[i]=rd(),y[i]=rd(); while(l<r) { mid=(l+r)>>1; if(check(mid)) l=mid+1; else r=mid; } printf("Case %d: ",cas); if(l==1000001) printf("never\n"); else printf("%d\n",l); } }//4 -3 5 3 4 -6 -2 1 -5 1 0 -1 -1
【BZOJ3958】[WF2011]Mummy Madness 二分+掃描線+線段樹