Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

我的第一篇洛谷博客就是扫描线。虽然那时候什么也不懂,也非常幼稚,甚至不知扫描线的原理是如何,只是一门心思地去做,就像面对未知的生活。

扫描线处理矩阵面积之和的问题,当然它们会有互相覆盖而不能直接加起来。

扫描线就是从下往上一次扫描“线”,然后用线将图分成多个区域,累加即可。用线段树记录横坐标此时扫描线处的长度。

Xi 表示第 \(i\) 条竖直的线(用来划分区间),用 line 结构体表示线水平的线。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define R register
using namespace std;
typedef long long ll;
inline int read()
{
int x=0,w=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
return w?-x:x;
}
const int maxn=1e6+10;
struct Line{
ll l,r,h;
int val;
bool operator < (const Line &zp) const {return h<zp.h;}
}line[maxn<<1];
int n;
ll X[maxn<<1];
struct SegmentTree
{
#define ls (ro<<1)
#define rs (ro<<1|1)
int l,r,sum;
struct tree{
int l,r,sum;
ll len;
}e[maxn<<2];
inline void pushup(int ro)
{
if(e[ro].sum)e[ro].len=X[e[ro].r+1]-X[e[ro].l];
else e[ro].len=e[ls].len+e[rs].len;
}
void build(int ro,int l,int r)
{
e[ro].l=l,e[ro].r=r;
if(l==r)return;
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
}
void update(int ro,int l,int r,int val)
{
if(X[e[ro].r+1]<=l or r<=X[e[ro].l])return;
if(l<=X[e[ro].l] and X[e[ro].r+1]<=r)
{
e[ro].sum+=val;
pushup(ro);
return;
}
update(ls,l,r,val);
update(rs,l,r,val);
pushup(ro);
}
#undef ls
#undef rs
}seg;
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
ll x1=(ll)read(),y1=(ll)read(),x2=(ll)read(),y2=(ll)read();
line[(i<<1)-1]=(Line){x1,x2,y1,1};
line[i<<1]=(Line){x1,x2,y2,-1};
X[(i<<1)-1]=x1,X[i<<1]=x2;
}
n<<=1;
sort(line+1,line+n+1);
sort(X+1,X+n+1);
int cnt=unique(X+1,X+n+1)-X-1;
seg.build(1,1,cnt-1);
ll ans=0;
for(register int i=1;i<n;i++)
{
seg.update(1,line[i].l,line[i].r,line[i].val);
ans+=seg.e[1].len*(line[i+1].h-line[i].h);
}
printf("%lld\n",ans);
return 0;
}

给小狼留言