標籤:std == sort cst https sam pair inpu using
Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 1394 Solved: 625
[Submit][Status][Discuss]
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),即一個黑點的座標。沒有兩個黑點的座標相同,座標的絕對值均不超過\(10 ^9\)。
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
掃描線板子題
易發現所有能變色的白點一定在第一秒就能變色,上下左右都有黑點。而且永不停止是不可能的。
把黑點離散化,按y排一下序,用vector在每一列的上端點存1,下端點存-1到每一行,順便找出每一行的左端點和右端點用數組存下來
最後按行掃一遍,先加上端點再區間查詢這一行的左右段點再減下端點即可
#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<cstring>using namespace std;int i,m,n,j,k,zl[100001],zr[100001],x,y,l,r,ll[100001],rr[100001],c[100001],ans;struct vv{ int x,y; } a[100001],b[100001];vector <pair<int,int> > q[100001], p[100001];bool cmp2(vv a,vv b) {if(a.y==b.y) return a.x<b.x; return a.y<b.y;}void add(int now,int z) { for(int i=now;i<=y;i+=i & -i) c[i]+=z;}int ask(int now){ int ans=0; for(int i=now;i>0;i-=i & -i) ans+=c[i]; return ans; }int main(){ scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d%d",&a[i].x,&a[i].y); zl[i]=a[i].x; zr[i]=a[i].y; } sort(zl+1,zl+1+n); sort(zr+1,zr+1+n); x=unique(zl+1,zl+1+n)-zl-1; y=unique(zr+1,zr+1+n)-zr-1; for(i=1;i<=n;i++) { a[i].x=lower_bound(zl+1,zl+1+x,a[i].x)-zl, a[i].y=lower_bound(zr+1,zr+1+y,a[i].y)-zr; b[i].x=a[i].x; b[i].y=a[i].y; } sort(a+1,a+1+n,cmp2); l=0x3f3f3f3f; r=0; memset(ll,0x3f,sizeof(ll)); for(i=1;i<=n;i++) { if(a[i].y!=a[i-1].y) { if(r) p[r].push_back(make_pair(a[i-1].y,-1)), q[l].push_back(make_pair(a[i-1].y,1)); l=0x3f3f3f3f; r=0; } l=min(a[i].x,l); r=max(a[i].x,r); ll[a[i].x]=min(ll[a[i].x],a[i].y); rr[a[i].x]=max(rr[a[i].x],a[i].y); } if(r) p[r].push_back(make_pair(a[n].y,-1)), q[l].push_back(make_pair(a[n].y,1)); for(i=1;i<=x;i++) { for(j=0;j<q[i].size();j++) add(q[i][j].first,q[i][j].second); if(rr[i]) ans+=ask(rr[i])-ask(ll[i]-1); for(j=0;j<p[i].size();j++) add(p[i][j].first,p[i][j].second); } printf("%d",ans);}
1818: [Cqoi2010]內部白點