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
题意:一个无限大的棋盘上有无数个点,这些点有黑有白,如果有一个点,上下左右各有点,则将这个点涂成黑色。最后计算这个棋盘上黑点的数量
解题思路:先将坐标离散化,然后判断出对于每个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;
}