BZOJ1818: [Cqoi2010]內部白點
阿新 • • 發佈:2017-09-07
所有 水平 b+ 答案 light 豎直 discuss status main
Submit: 1004 Solved: 485
[Submit][Status][Discuss]
輸入第一行包含一個整數n,即初始黑點個數。以下n行每行包含兩個整數(x,y),即一個黑點的坐標。沒有兩個黑點的坐標相同,坐標的絕對值均不超過109。
0 2
2 0
-2 0
0 -2
數據範圍
36%的數據滿足:n < = 500
64%的數據滿足:n < = 30000
100%的數據滿足:n < = 100000
1818: [Cqoi2010]內部白點
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1004 Solved: 485
[Submit][Status][Discuss]
Description
無限大正方形網格裏有n個黑色的頂點,所有其他頂點都是白色的(網格的頂點即坐標為整數的點,又稱整點)。每秒鐘,所有內部白點同時變黑,直到不存在內部白點為止。你的任務是統計最後網格中的黑點個數。 內部白點的定義:一個白色的整點P(x,y)是內部白點當且僅當P在水平線的左邊和右邊各至少有一個黑點(即存在x1 < x < x2使得(x1,y)和(x2,y)都是黑點),且在豎直線的上邊和下邊各至少有一個黑點(即存在y1 < y < y2使得(x,y1)和(x,y2)都是黑點)。Input
Output
輸出僅一行,包含黑點的最終數目。如果變色過程永不終止,輸出-1。Sample Input
40 2
2 0
-2 0
0 -2
Sample Output
5數據範圍
36%的數據滿足:n < = 500
64%的數據滿足:n < = 30000
100%的數據滿足:n < = 100000
思路{
想怎麽統計呢,發現在第一次一定算完了所有的點.那麽現在問題變成了算有多少個點滿足上下左右都有點.
不妨轉化為線段求交.抽象成一些橫線,豎線.豎線交橫線產生貢獻.
怎麽統計貢獻呢???
好的,用從下往上的掃描線就可以了,
碰到豎線下端點,x坐標位置+1,上端點的話-1.遇到橫線統計一段x之內的答案就可以了
註意同一高度線段的掃描順序可以把豎線拆成兩個點.
}
#include<iostream> #include<cstdlib> #include<cstdio> #include<algorithm> #define N 1000001 #define lowbit ( (i) & (-i) ) #define LL long long using namespace std; struct point{ int x,y; void read(){scanf("%d%d",&x,&y);} }p[N]; struct seg{ int h1,h2,h3,flag; seg() {} seg(int x,int y,int z,int a):h1(x),h2(y),h3(z),flag(a) {} }s[N]; int tree[N],n,tot,sz,sub[N]; void Insert(int pos,int num){for(int i=pos;i<=n;i+=lowbit)tree[i]+=num;} int Query(int pos){int sum(0);for(int i=pos;i;i-=lowbit)sum+=tree[i];return sum;} int find(int x){ return lower_bound(sub+1,sub+sz+1,x)-sub; } void link(int ff,int l,int r,int h){//0橫線,1豎線 if(!ff){ s[++tot]=seg(find(l),find(r),h,0); }else { int X=find(h); s[++tot]=seg(X,X,l,1); s[++tot]=seg(X,X,r,-1); } } bool comp(const point & a,const point & b){return a.x==b.x?a.y<b.y:a.x<b.x;} bool Comp(const point & a,const point & b){return a.y==b.y?a.x<b.x:a.y<b.y;} bool COMP(const seg & a,const seg & b){ if(a.h3!=b.h3)return a.h3<b.h3; return a.flag<b.flag; } void build(){ sort(p+1,p+n+1,comp); for(int i=2;i<=n;++i) if(p[i].x==p[i-1].x) link(1,p[i-1].y,p[i].y,p[i].x); sort(p+1,p+n+1,Comp); for(int i=2;i<=n;++i) if(p[i].y==p[i-1].y) link(0,p[i-1].x,p[i].x,p[i].y); sort(s+1,s+tot+1,COMP); } int main(){ scanf("%d",&n); for(int i=1;i<=n;++i)p[i].read(),sub[++sub[0]]=p[i].x; sort(sub+1,sub+sub[0]+1); sz=unique(sub+1,sub+sub[0]+1)-sub-1; build();LL Ans(0); for(int i=1;i<=tot;++i){ if(!s[i].flag)Ans+=Query(s[i].h2-1)-Query(s[i].h1); else Insert(s[i].h1,s[i].flag); }cout<<Ans+n; return 0; }
BZOJ1818: [Cqoi2010]內部白點