题目描述
无限大正方形网格里有 nn 个黑色的顶点,所有其他顶点都是白色的(网格的顶点即坐标为整数的点,又称整点)。每秒钟,所有内部白点同时变黑,直到不存在内部白点为止。你的任务是统计最后网格中的黑点个数。
内部白点的定义:一个白色的整点 P(x,y) 是内部白点当且仅当 PP 在水平线的左边和右边各至少有一个黑点(即存在x_1 < x < x_2 使得 (x_1 , y) 和 (x_2 , y) 都是黑点),且在竖直线的上边和下边各至少有一个黑点(即存在 y_1 < y < y_2 使得 (x,y_1) 和 (x,y_2)) 都是黑点)。
输入格式
输入第一行包含一个整数 n,即初始黑点个数。
以下 nn 行每行包含两个整数 x,y,即一个黑点的坐标。没有两个黑点的坐标相同,坐标的绝对值均不超过 10^9 。
输出格式
输出仅一行,包含黑点的最终数目。
如果变色过程永不终止,输出-1。
输入输出样例
输入 #1复制
4
0 2
2 0
-2 0
0 -2
输出 #1复制
5
说明/提示
数据范围
对于 36% 的数据,n≤500。
对于 64% 的数据,n≤3×10^4 。
对于 100% 的数据,n≤10^5 。
一个很坑的事实是不会有-1的情况,为啥?(你puts("-1")试试啊)
其实是因为,一个点能否变成黑点与他上下左右四个点有关,准确的说是和最上面,最左面,。。的有关。
而一个点他被其他点变成了黑色,那肯定是有比他靠左,比他靠上。。。的(。。。自行脑补,我太懒了)
然后把横坐标相同的连一块,纵坐标相同的连一块。
像这样(图是ez_lcw巨佬的)
然后扫描线解决。。
将x离散化,按y排序,从下往上扫。。具体的看代码吧,各位巨佬肯定能看懂
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
const int N = 1e5+10;
inline int read()
{
register int x = 0 , f = 0; register char c = getchar();
while(c < '0' || c > '9') f |= c == '-' , c = getchar();
while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0' , c = getchar();
return f ? -x : x;
}
int n;
int a[N];
struct point{ int x , y; }p[N];
struct Line{ int val , x , y , z; }s[N * 3];
inline bool cmp(const Line &A , const Line &B) { return A.y == B.y ? A.val < B.val : A.y < B.y; }
inline bool cmpx(const point &A , const point &B) { return A.x == B.x ? A.y < B.y : A.x < B.x; }
inline bool cmpy(const point &A , const point &B) { return A.y == B.y ? A.x < B.x : A.y < B.y; }
namespace BIT
{
LL tr[N];
void Add(int pos , int val) { if(pos <= 0) return ; while(pos <= n) tr[pos] += val , pos += (pos & (-pos)); return ; }
LL Ask(int pos) { if(pos <= 0) return 0LL; LL ans = 0LL; while(pos) ans += tr[pos] , pos -= (pos & (-pos)); return ans; }
}
int main()
{
n = read();
for(int i = 1 ; i <= n ; ++i) a[i] = p[i].x = read() , p[i].y = read();
sort(a + 1 , a + 1 + n); int tot = unique(a + 1 , a + 1 + n) - a - 1;
for(int i = 1 ; i <= n ; ++i) p[i].x = lower_bound(a + 1 , a + 1 + tot , p[i].x) - a;
sort(p + 1 , p + 1 + n , cmpx); tot = 0;
for(int i = 2 ; i <= n ; ++i)
if(p[i].x == p[i-1].x)
s[++tot].val = 1 , s[tot].x = p[i].x , s[tot].y = p[i-1].y ,
s[++tot].val = -1 , s[tot].x = p[i].x , s[tot].y = p[i].y;
sort(p + 1 , p + 1 + n , cmpy);
for(int i = 2 ; i <= n ; ++i)
if(p[i].y == p[i-1].y)
s[++tot].val = 0 , s[tot].x = p[i-1].x , s[tot].z = p[i].x , s[tot].y = p[i].y;
sort(s + 1 , s + 1 + tot , cmp);
using namespace BIT;
LL ans = n;
for(int i = 1 ; i <= tot ; ++i)
if(s[i].val) Add(s[i].x , s[i].val); else ans += Ask(s[i].z - 1) - Ask(s[i].x); // 不包括两端
cout << ans << '
';
return 0;
}