1. 程式人生 > >bzoj1818 [Cqoi2010]內部白點

bzoj1818 [Cqoi2010]內部白點

一個 add 正方形 pac get 數組 h+ 是否 endif

Description

無限大正方形網格裏有n個黑色的頂點,所有其他頂點都是白色的(網格的頂點即坐標為整數的點,又稱整點)。每秒鐘,所有內部白點同時變黑,直到不存在內部白點為止。你的任務是統計最後網格中的黑點個數。 內部白點的定義:一個白色的整點P(x,y)是內部白點當且僅當P在水平線的左邊和右邊各至少有一個黑點(即存在x1 < x < x2使得(x1,y)和(x2,y)都是黑點),且在豎直線的上邊和下邊各至少有一個黑點(即存在y1 < y < y2使得(x,y1)和(x,y2)都是黑點)。

Input

輸入第一行包含一個整數n,即初始黑點個數。以下n行每行包含兩個整數(x,y),即一個黑點的坐標。沒有兩個黑點的坐標相同,坐標的絕對值均不超過109。

Output

輸出僅一行,包含黑點的最終數目。如果變色過程永不終止,輸出-1。

Sample Input

4
0 2
2 0
-2 0
0 -2

Sample Output

5
數據範圍
36%的數據滿足:n < = 500
64%的數據滿足:n < = 30000
100%的數據滿足:n < = 100000

正解:掃描線+樹狀數組。

容易發現,如果一個白點的上下左右都有黑點,那麽它就能變成白點。

所以點是可以直接離散化的,無數點的情況也是沒有的。

於是直接寫一個掃描線,掃描每一列,然後用樹狀數組統計每一行是否上下都有黑點就行了。

 1 #include <bits/stdc++.h>
 2
#define il inline 3 #define RG register 4 #define ll long long 5 #define lb(x) (x & -x) 6 #define inf (1<<30) 7 #define N (100005) 8 9 using namespace std; 10 11 struct point{ int x,y; }p[N]; 12 13 vector<int> g[N]; 14 int hsh[N],num[N],cnt[N],can[N],c[N],mn[N],mx[N],n,tot;
15 ll ans; 16 17 il int gi(){ 18 RG int x=0,q=1; RG char ch=getchar(); 19 while ((ch<0 || ch>9) && ch!=-) ch=getchar(); 20 if (ch==-) q=-1,ch=getchar(); 21 while (ch>=0 && ch<=9) x=x*10+ch-48,ch=getchar(); 22 return q*x; 23 } 24 25 il void add(RG int x,RG int v){ 26 for (;x<=n;x+=lb(x)) c[x]+=v; return; 27 } 28 29 il int query(RG int x){ 30 RG int res=0; 31 for (;x;x^=lb(x)) res+=c[x]; return res; 32 } 33 34 int main(){ 35 #ifndef ONLINE_JUDGE 36 freopen("white.in","r",stdin); 37 freopen("white.out","w",stdout); 38 #endif 39 n=gi(); 40 for (RG int i=1;i<=n;++i) hsh[++tot]=p[i].x=gi(),p[i].y=gi(); 41 sort(hsh+1,hsh+tot+1),tot=unique(hsh+1,hsh+tot+1)-hsh-1; 42 for (RG int i=1;i<=n;++i) p[i].x=lower_bound(hsh+1,hsh+tot+1,p[i].x)-hsh; 43 for (RG int i=1;i<=n;++i) mn[i]=inf,mx[i]=0; 44 tot=0; for (RG int i=1;i<=n;++i) hsh[++tot]=p[i].y; 45 sort(hsh+1,hsh+tot+1),tot=unique(hsh+1,hsh+tot+1)-hsh-1; 46 for (RG int i=1;i<=n;++i) p[i].y=lower_bound(hsh+1,hsh+tot+1,p[i].y)-hsh; 47 for (RG int i=1;i<=n;++i){ 48 g[p[i].x].push_back(i),++cnt[p[i].y]; 49 mn[p[i].x]=min(mn[p[i].x],p[i].y),mx[p[i].x]=max(mx[p[i].x],p[i].y); 50 } 51 for (RG int i=1;i<=n;++i){ 52 if (mn[i]>mx[i]) continue; 53 for (RG int j=0,k;j<g[i].size();++j){ 54 k=p[g[i][j]].y,++num[k]; 55 if (can[k]!=(num[k]&&cnt[k])) add(k,1),can[k]=1; 56 } 57 if (mn[i]!=mx[i]) ans+=query(mx[i]-1)-query(mn[i])+2; else ++ans; 58 for (RG int j=0,k;j<g[i].size();++j){ 59 k=p[g[i][j]].y,--cnt[k]; 60 if (can[k]!=(num[k]&&cnt[k])) add(k,-1),can[k]=0; 61 } 62 } 63 cout<<ans; return 0; 64 }

bzoj1818 [Cqoi2010]內部白點