扫描线
求矩形面积并,把矩阵竖着割开,累加。
矩形 \((x_1,y_1,x_2,y_2)\) 分成 \((x1,y1,y2,1)\) 和 \((x2,y1,y2,-1)\) 两条线,指的是,\(x=x_i(y_1\leq x\leq y_2)\) 这样的线,土 \(1\) 指的是加上或减去。
需要离散 flower,主要是 SGT。
不断维护当前的矩阵高,线段树搞。
线段树要维护 当前区间覆盖次数|区间总高度。
因为是修改成对,所以可以 乱搞 简单搞 qwq
把实际上的组成区间 \(cnt\) 改掉,每次上传 \(pushup\)。
当前节点 \(cnt>0\) 的情况 \(len=\) 区间实际长度,不然是左右子树 \(len\) 和。
注意开 \(16n\) 空间,划分 \(*2\) 线段树 \(*8\) /fad
#include<bits/stdc++.h>
#define int long long
#define MN 1600010
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
using namespace std;
int n, raw[MN], cnt[MN], len[MN];
int top, tot, ans;
struct dat {
int x, l, r, k;
dat() {}
dat(int xx,int ll,int rr,int kk)
{ x=xx, l=ll, r=rr, k=kk; }
} p[MN];
bool cmp(dat u,dat v)
{ return u.x<v.x; }
inline void up(int p,int s,int e) {
if(cnt[p]) len[p]=raw[e]-raw[s];
else len[p]=len[ls(p)]+len[rs(p)];
}
void upt(int p,int s,int e,int l,int r,int v) {
if(l>=raw[e]||raw[s]>=r) return;
if(l<=raw[s]&&raw[e]<=r) {
cnt[p]+=v;
up(p,s,e);
return;
}
int mid=(s+e)>>1;
upt(ls(p),s,mid,l,r,v);
upt(rs(p),mid,e,l,r,v);
up(p,s,e);
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n;
for(int i=1; i<=n; ++i) {
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
p[++top]=dat(x1,y1,y2,1), raw[top]=y1;
p[++top]=dat(x2,y1,y2,-1), raw[top]=y2;
}
sort(raw+1,raw+1+top);
for(int i=1; i<=top; ++i)
if(raw[i]!=raw[i-1]) raw[++tot]=raw[i];
sort(p+1,p+1+top,cmp);
for(int i=1; i<top; ++i) {
upt(1,1,tot,p[i].l,p[i].r,p[i].k);
ans+=(p[i+1].x-p[i].x)*len[1];
}
cout << ans;
return 0;
}