POJ3109-Inner Vertices

Inner Vertices
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 2583 Accepted: 739
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


题意:一个无限大的棋盘上有无数个点,这些点有黑有白,如果有一个点,上下左右各有点,则将这个点涂成黑色。最后计算这个棋盘上黑点的数量

解题思路:先将坐标离散化,然后判断出对于每个x轴的最高的y。对所有点可以按y轴从小到大进行排序,y轴相同的按x轴从小到大进行排序。每扫到一个点,若这个点不是这个x轴的最高的y,则在线段树上将这个位置置为一,否则的话置为0。扫的时候若前后两个点的y坐标一样,则查询一下在这两个x轴之间区间值为多少,则答案就加多少


#include <iostream>    
#include <cstdio>    
#include <string>    
#include <cstring>    
#include <algorithm>    
#include <cmath>    
#include <vector>    
#include <map>    
#include <set>    
#include <queue>    
#include <stack>    
#include <functional>    
#include <climits>    

using namespace std;

#define LL long long    
const int INF = 0x3f3f3f3f;

int n, x[100009], y[100009], sum[100009 << 2], f[100009];

struct point
{
	int x, y;
	bool operator<(const point &b)const
	{
		if (y != b.y) return y < b.y;
		else return x < b.x;
	}
}p[100009];

void update(int k, int l, int r, int p, int val)
{
	if (l == r) { sum[k] = val; return; }
	int mid = (l + r) >> 1;
	if (mid >= p) update(k << 1, l, mid, p, val);
	else update(k << 1 | 1, mid + 1, r, p, val);
	sum[k] = sum[k << 1] + sum[k << 1 | 1];
}

int query(int k, int l, int r, int ll, int rr)
{
	if (l >= ll&&r <= rr) return sum[k];
	int mid = (l + r) >> 1, ans = 0;
	if (ll <= mid) ans += query(k << 1, l, mid, ll, rr);
	if (rr > mid) ans += query(k << 1 | 1, mid + 1, r, ll, rr);
	return ans;
}

int main()
{
	while (~scanf("%d", &n))
	{
		memset(f, 0, sizeof f);
		int cnt1 = 1, cnt2 = 1;
		for (int i = 1; i <= n; i++)
		{
			scanf("%d%d", &p[i].x, &p[i].y);
			x[cnt1++] = p[i].x, y[cnt2++] = p[i].y;
		}
		sort(p + 1, p + 1 + n);
		sort(x + 1, x + cnt1);
		sort(y + 1, y + cnt2);
		cnt1 = unique(x + 1, x + cnt1) - x;
		cnt2 = unique(y + 1, y + cnt2) - y;
		memset(sum, 0, sizeof sum);
		for (int i = n; i >= 1; i--)
		{
			int xx = lower_bound(x + 1, x + cnt1, p[i].x) - x;
			int yy = lower_bound(y + 1, y + cnt2, p[i].y) - y;
			if (f[xx]) continue;
			f[xx] = yy;
		}
		int ans = 0;
		for (int i = 1; i <= n; i++)
		{
			int xx = lower_bound(x + 1, x + cnt1, p[i].x) - x;
			int yy = lower_bound(y + 1, y + cnt2, p[i].y) - y;
			if (f[xx] > yy) update(1, 1, cnt1, xx, 1);
			else update(1, 1, cnt1, xx, 0);
			if (i == 1 || p[i].y != p[i - 1].y) continue;
			int l = lower_bound(x + 1, x + cnt1, p[i - 1].x) - x + 1;
			int r = xx - 1;
			if (l > r) continue;
			ans += query(1, 1, cnt1, l, r);
		}
		printf("%d\n", ans + n);
	}
	return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值