Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 1815 | Accepted: 479 | |
Case Time Limit: 2000MS |
Description
There is an infinite square grid. Some vertices of the grid are black and other vertices are white.
A vertex V is called inner if it is both vertical-inner and horizontal-inner. A vertex V is called horizontal-inner if there are two such black vertices in the same row that V is located between them. A vertex V is called vertical-inner if there are two such black vertices in the same column that V is located between them.
On each step all white inner vertices became black while the other vertices preserve their colors. The process stops when all the inner vertices are black.
Write a program that calculates a number of black vertices after the process stops.
Input
The first line of the input file contains one integer number n (0 ≤ n ≤ 100 000) — number of black vertices at the beginning.
The following n lines contain two integer numbers each — the coordinates of different black vertices. The coordinates do not exceed 109 by their absolute values.
Output
Output the number of black vertices when the process stops. If the process does not stop, output -1
.
Sample Input
4 0 2 2 0 -2 0 0 -2
Sample Output
5
Hint
![](https://i-blog.csdnimg.cn/blog_migrate/19b7207cf07cc68d61505e691c646f69.png)
Source
第一次碰到扫描线的题,不会做。。。学习了下http://blog.csdn.net/lolicon480/article/details/44183397
先将点坐标离散化后,按y轴排序。用一条扫描线,在y轴从下往上扫描。
扫描到一个点(x,y),如果它不是直线上X=x最顶端的点(说明它上面有别的点,因此有可能形成新的黑点,如上面图中最低端的那个点),就对bit执行一次add(x,1)。
如果当前Y=y上有两个点,坐标为(x1,y)(x2,y),则它们之间会形成的黑点取决于区域(x1+1,x2-1)上有多少对端点,也就是用bit统计的sum(x2-1)-sum(x1)。
如果扫描到点(x,y),并且它是直线上X=x最顶端的点(上图最上面的那个),那么X=x这条直线上不可能产生新的点了,消去之前添加的1--add(x,-1)(如果出现过)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define maxn 100001
int bit[maxn];
int hash[maxn];
int end[maxn];
void add(int i, int x)
{
while(i<maxn){
bit[i]+=x;
i+=i&-i;
}
}
int sum(int i)
{
int res=0;
while(i>0){
res+=bit[i];
i-=i&-i;
}
return res;
}
struct P
{
int x,y;
/* data */
};
int cmpx(const P &a, const P &b)
{
return a.x!=b.x?a.x<b.x:a.y<b.y;
}
int cmpy(const P &a, const P &b)
{
return a.y!=b.y?a.y<b.y:a.x<b.x;
}
P a[maxn];
int main()
{
int n;
while(scanf("%d",&n)==1){
memset(bit, 0, sizeof(bit));
memset(hash, 0, sizeof(hash));
memset(end, 0, sizeof(end));
for(int i=0; i<n; i++)
scanf("%d%d",&a[i].x, &a[i].y);
sort(a,a+n,cmpx);
int cnt=1;
for(int i=0; i<n; i++){ //离散化
int t=a[i].x;
a[i].x=cnt;
if(t!=a[i+1].x)
cnt++;
}
sort(a, a+n, cmpy);
cnt=1;
for(int i=0; i<n; i++){
int t=a[i].y;
a[i].y=cnt;
if(t!=a[i+1].y)
cnt++;
}
for(int i=0; i<n; i++) //记录顶端的点y坐标是哪些
end[a[i].x]=max(end[a[i].x],a[i].y);
int ans=n;
for(int i=0; i<n; i++){
if(!hash[a[i].x]&&a[i].y!=end[a[i].x]){ //不是顶端的点,+1
add(a[i].x,1);
hash[a[i].x]=1;
}
if(a[i].y==a[i+1].y){ //y坐标相同,统计(x2-1,x1+1)有多少对
ans+=sum(a[i+1].x-1)-sum(a[i].x);
}
if(hash[a[i].x]&&a[i].y==end[a[i].x]){ //是顶端的点,消除影响-1
add(a[i].x,-1);
}
}
cout<<ans<<endl;
}
}