扫描线

扫描线

引入

扫描线一般运用在图形上面,它和它的字面意思十分相似,就是在一整个图上面扫来扫去。最经典的还是二维矩形面积并问题

二维矩形面积并

P5490 【模板】扫描线 & 矩形面积并

在二维平面上给出若干个矩形,求所有矩形构成的图形的并。

过程

先放一张不要钱捡来的图片。

oi-wiki.org/geometry/images/scanning.svg

懂了吧?是不是很简单?

相信你已经懂了。

其实这张图在这里,这篇学习笔记就已经写完了。

具体的

我们可以搞一个线段树,然后维护一下这个东西,然后这么搞一下,就可以了。

参考代码

参考自 UKE_Automation 的博客

代码不难理解,线段树需要注意的每一个节点对应的是线段上的端点,所以写法略不同于序列(具体的,线段树维护的区间右端点要加一)。另外,由于题目数据范围是 1e9 级别,所以要离散化。注释懒得写了,参考原文。


// P5490 【模板】扫描线 & 矩形面积并
#include <bits/stdc++.h>
#define int long long  

using namespace std;

int read() {
	int x = 0; char ch = getchar();
	while (ch < '0' || ch > '9') ch = getchar();
	while (ch >= '0' && ch <= '9') {
		x = (x << 1) + (x << 3) + (ch ^ 48);
		ch = getchar();
	}
	return x;
}
const int N = 4e5 + 10;
int n;
struct seg {
	int l, r, h, t;
	bool operator < (const seg & cmp) const {
		return h != cmp.h ? h < cmp.h : t > cmp.t;
	}
} a[N];
int b[N];
struct node {
	int l, r, s, len, lazy;
} tree[4 * N];
#define lc p << 1
#define rc p << 1 | 1
void pushup(int p) {
	if (tree[p].s) {
		tree[p].len = b[tree[p].r + 1] - b[tree[p].l];
	} else {
		tree[p].len = tree[lc].len + tree[rc].len;
	}
} 
void build(int p, int l, int r) {
	tree[p].l = l, tree[p].r = r;
	if (l == r) return;
	int mid = l + r >> 1;
	build(lc, l, mid);
	build(rc, mid + 1, r);
}
void update(int p, int l, int r, int v) {
	if (tree[p].r + 1 <= l || r <= tree[p].l) return;
	if (l <= tree[p].l && tree[p].r + 1 <= r) {
		tree[p].s += v;
		pushup(p);
		return;
	} 
	update(lc, l, r, v);
	update(rc, l, r, v);
	pushup(p);
}
signed main() {
	n = read();
	for (int i = 1; i <= n; i++) {
		int A = read(), B = read(), C = read(), D = read();
		b[2 * i - 1] = A;
		b[2 * i] = C;
		a[2 * i - 1] = {A, C, B, 1}; 
		a[2 * i] = {A, C, D, -1};
	}
	n *= 2;
	sort(a + 1, a + 1 + n);
	sort(b + 1, b + 1 + n);
	int ll = unique(b + 1, b + 1 + n) - b - 1;
	for (int i = 1; i <= n; i++) {
		a[i].l = lower_bound(b + 1, b + 1 + ll, a[i].l) - b;
		a[i].r = lower_bound(b + 1, b + 1 + ll, a[i].r) - b;
	}
	build(1, 1, ll - 1);
	int ans = 0;
	for (int i = 1; i <= n; i++) {
		update(1, a[i].l, a[i].r, a[i].t);
		ans += (a[i + 1].h - a[i].h) * tree[1].len;
	}
	printf("%lld\n", ans);
	
	return 0;
}
posted @ 2025-03-16 17:41  Zctf1088  阅读(18)  评论(0)    收藏  举报