[模板]扫描线
[模板]扫描线求面积并
题目概述
给定矩形信息(以左下、右上顶点坐标为例),求矩形总覆盖面积
算法概述
-
将给定的其中一维坐标离散化, 以此维所有坐标为断点将整个图形分割为若干小矩形(以x维为例)
-
模拟一条扫描线扫过整个图形的过程,某一时刻扫描线覆盖到的线段长度为小矩形的一条边长,另一条边长则为未离散的一维的相邻坐标差(以y维为例)
-
使用线段树维护某一时刻扫描线覆盖的区间长度:将(与扫描线)靠近扫描起点的矩形边权(以下边为例)值赋为1,对边为-1,则
tre[1].len
则为此时扫描线覆盖的线段长
注意事项
-
线段树的
l
和r
并非实际区间边界而是离散化后的点编号,每个点编号x
代表点x
到点x + 1
之间的线段,故实际边界为[a[l],a[r + 1]]
-
对于每个矩形有两个点信息和边信息需要储存,故储存点信息的数组大小和储存边信息的结构体数组大小都为
n << 1
-
在对叶子节点执行
pushup
操作时会访问rt << 1
和rt << 1 | 1
,故线段树数组大小为n << 4
(普通线段树为n << 2
,矩形点和边信息为n << 1
,叶子节点pushup
为n << 1
,结合为n << 4
)
代码
#include <iostream>
#include <algorithm>
#define ll long long
using namespace std;
struct Lines{
int l, r, h, key;
bool operator < (const Lines &a) const{
return h < a.h;
}
}lne[2000010];
struct Trees{
int l, r, sum;
ll len;
}tre[1600010];
int n, a[1000010];
void pushup(int rt){
int l = tre[rt].l, r = tre[rt].r;
if(tre[rt].sum)
tre[rt].len = a[r + 1] - a[l];
else
tre[rt].len = tre[rt << 1].len + tre[rt << 1 | 1].len;
}
void build(int rt, int l, int r){
tre[rt].l = l, tre[rt].r = r, tre[rt].len = tre[rt].sum = 0;
if(l == r) return;
int mid = (l + r) >> 1;
build(rt << 1, l, mid), build(rt << 1 | 1, mid + 1, r);
}
void edit(int rt, ll x, ll y, int z){
int l = tre[rt].l, r = tre[rt].r, mid = (l + r) >> 1;
if(a[r + 1] <= x || y <= a[l]) return;
if(x <= a[l] && y >= a[r + 1]){
tre[rt].sum += z, pushup(rt);
return;
}
if(x < a[mid + 1]) edit(rt << 1, x, y, z);
if(y > a[mid + 1]) edit(rt << 1 | 1, x, y, z);
pushup(rt);
}
int main(){
cin >> n;
int x1, x2, y1, y2;
for(int i = 1; i <= n; i++){
cin >> x1 >> y1 >> x2 >> y2;
a[2 * i - 1] = x1, a[2 * i] = x2;
lne[2 * i - 1] = (Lines) {x1, x2, y1, 1};
lne[2 * i] = (Lines) {x1, x2, y2, -1};
}
n <<= 1;
sort(lne + 1, lne + n + 1), sort(a + 1, a + n + 1);
int m = unique(a + 1, a + n + 1) - a - 1;
build(1, 1, m - 1);
ll ans = 0;
for(int i = 1; i <= n - 1; i++){
edit(1, lne[i].l, lne[i].r, lne[i].key);
ans += tre[1].len * (ll)(lne[i + 1].h - lne[i].h);
}
cout << ans << endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】