吐槽:现在做题再也不能想也不想就看题解了!!!QAQ!!否则我可能就没有未来了QAQ
好了不要管上面的吐槽qaq
题意:
平面上有n个黑点,剩下的整点全部是白点。
一个白点如果上下左右各至少有一个黑点就称内部白点。
现在每一次操作可以将所有的内部白点变成黑点,一直操作到不能操作为止。
问最后有多少的黑点。如果无法停止操作输出-1.
n<=105,坐标范围109
n
<=
10
5
,
坐
标
范
围
10
9
做法:
首先这个题面里很多东西都是假的qwq…没有-1的情况,而且最多只会操作一次。(显然)
于是我们发现要求的东西就是横线与竖线的交叉点有多少个。
然后就扫描线搞搞的事了qwq..
要注意的是,由于交叉点不能算某些原来就有的点,所以对于一个横坐标,假设这个横坐标上有 k k 个点,它们的纵坐标分别是,则需要分成 k−1 k − 1 个线段插入,且线段i的左右端点分别是 yi+1,yi+1−1 y i + 1 , y i + 1 − 1 。纵坐标同理。
代码:
/*************************************************************
Problem: bzoj 1818 [Cqoi2010]内部白点
User: fengyuan
Language: C++
Result: Accepted
Time: 1912 ms
Memory: 12028 kb
Submit_Time: 2018-01-31 18:09:23
*************************************************************/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<vector>
#define pb push_back
#define mp make_pair
#define F first
#define S second
#define lc o<<1
#define rc o<<1|1
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
inline ll read() {
char ch = getchar(); ll x = 0; int op = 1;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') op = -1;
for(; isdigit(ch); ch = getchar()) x = x*10+ch-'0';
return x*op;
}
inline void write(ll a) {
if(a < 0) putchar('-'), a = -a;
if(a >= 10) write(a/10); putchar('0'+a%10);
}
const int N = 100010;
int n, cx, cy, ans;
int xx[N], yy[N], t[N];
struct node { int x, y; }p[N];
vector<pii> tg[N], l[N];
vector<int> rp[N], cp[N];
inline void add(int k, int v) { for(int i = k; i <= cy; i += i&-i) t[i] += v; }
inline int sum(int k) { int ret = 0; for(int i = k; i; i -= i&-i) ret += t[i]; return ret; }
int main() {
n = read();
for(int i = 1; i <= n; i ++) {
p[i].x = read(); p[i].y = read();
xx[++ cx] = p[i].x; yy[++ cy] = p[i].y;
} sort(xx+1, xx+1+cx); sort(yy+1, yy+1+cy);
cx = unique(xx+1, xx+1+cx)-xx-1; cy = unique(yy+1, yy+1+cy)-yy-1;
for(int i = 1; i <= n; i ++) {
int x = lower_bound(xx+1, xx+1+cx, p[i].x)-xx, y = lower_bound(yy+1, yy+1+cy, p[i].y)-yy;
rp[x].pb(y); cp[y].pb(x);
}
for(int i = 1; i <= cx; i ++) sort(rp[i].begin(), rp[i].end());
for(int i = 1; i <= cy; i ++) sort(cp[i].begin(), cp[i].end());
for(int i = 1; i <= cx; i ++)
if((int)rp[i].size() > 1) {
for(int j = 1; j < (int)rp[i].size(); j ++) l[i].pb(mp(rp[i][j-1]+1, rp[i][j]-1));
}
for(int i = 1; i <= cy; i ++)
if((int)cp[i].size() > 1) {
for(int j = 1; j < (int)cp[i].size(); j ++) {
tg[cp[i][j-1]+1].pb(mp(i, 1));
tg[cp[i][j]].pb(mp(i, -1));
}
}
for(int i = 1; i <= cx; i ++) {
for(int j = 0; j < (int)tg[i].size(); j ++) add(tg[i][j].F, tg[i][j].S);
for(int j = 0; j < (int)l[i].size(); j ++) {
ans += sum(l[i][j].S)-sum(l[i][j].F-1);
}
}
write(ans + n); puts("");
return 0;
}