洛谷 P5490【模板】扫描线
题目链接
题目描述
求
n
n
n 个矩形的面积并。
输入格式
第一行一个正整数
n
n
n。
接下来
n
n
n 行每行四个非负整数
x
1
,
y
1
,
x
2
,
y
2
x_1, y_1, x_2, y_2
x1,y1,x2,y2,表示一个矩形的左下角坐标为
(
x
1
,
y
1
)
(x_1, y_1)
(x1,y1),右上角标为
(
x
2
,
y
2
)
(x_2, y_2)
(x2,y2)。
输出格式
一行一个正整数,表示
n
n
n 个矩形的并集覆盖的总面积。
输入输出样例
输入 #1
2
100 100 200 200
150 150 250 255
输出 #1
18000
说明/提示
对于 20% 的数据,
1
≤
n
≤
1000
1≤n≤1000
1≤n≤1000。
对于 100% 的数据,
1
≤
n
≤
1
0
5
,
0
≤
x
1
<
x
2
≤
1
0
9
,
0
≤
y
1
<
y
2
≤
1
0
9
1≤n≤10^5,0≤x_1<x_2≤10^9,0≤y_1<y_2 ≤10^9
1≤n≤105,0≤x1<x2≤109,0≤y1<y2≤109。
AC代码
#include<cstdio>
#include<algorithm>
const int maxn = 2e5 + 5;
int v[maxn];
struct L {
int x, y1, y2, state;
bool operator<(const L &oth) const { return x < oth.x; }
} line[maxn];
struct node { //线段树
int l, r, cover;
long long len;
} sgt[maxn << 3];
inline int ls(int k) { return k << 1; }
inline int rs(int k) { return k << 1 | 1; }
inline void push_up(int k) {
if (sgt[k].cover)sgt[k].len = sgt[k].r - sgt[k].l;
else sgt[k].len = sgt[ls(k)].len + sgt[rs(k)].len;
}
void build(int l, int r, int k = 1) {
sgt[k].l = v[l];
sgt[k].r = v[r];
if (r - l <= 1)return;
int m = (l + r) >> 1;
build(l, m, ls(k));
build(m, r, rs(k));
}
void modify(int x, int y, int z, int k = 1) {
int l = sgt[k].l, r = sgt[k].r;
if (x <= l && r <= y) {
sgt[k].cover += z;
push_up(k);
return;
}
if (x < sgt[ls(k)].r) modify(x, y, z, ls(k));
if (y > sgt[rs(k)].l) modify(x, y, z, rs(k));
push_up(k);
}
int main() {
int a, b, c, d, n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d%d%d%d", &a, &b, &c, &d);
v[i] = b, v[n + i] = d;
line[i] = (L) {a, b, d, 1}, line[n + i] = (L) {c, b, d, -1};
}
n <<= 1;
std::sort(v + 1, v + n + 1);
std::sort(line + 1, line + n + 1);
build(1, n);
long long ans = 0;
for (int i = 1; i <= n; ++i) {
ans += sgt[1].len * (line[i].x - line[i - 1].x);
modify(line[i].y1, line[i].y2, line[i].state);
}
printf("%lld\n", ans);
return 0;
}