poj 3109 扫描线+bit

Inner Vertices
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

Source

Northeastern Europe 2005, Northern Subregion

第一次碰到扫描线的题,不会做。。。学习了下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;


	}
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值