扫描线结合线段树求矩形面积并
https://www.luogu.com.cn/problem/P5490
题意概述
给定二维平面上一系列矩形的四个坐标,求所有矩形的面积并。
思路
考虑对 \(x\) 轴做扫描线,每个事件触发前累加一次面积,\(y\) 轴覆盖的区域用线段树维护。线段树维护区间的有效长度和被整体覆盖的次数,如果整体覆盖次数大于 \(1\),有效长度为区间长度,否则为左右孩子的有效长度之和,不需要懒标记。注意 \(y\) 轴坐标需要离散化。
//author:kzssCCC
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = 9e18;
class node{
public:
ll len=0,cover=0;
int cnt=0;
};
void solve(){
int n;
cin >> n;
vector<ll> uni{0};
vector<array<ll,4>> a(n);
for (int i=0;i<n;i++){
ll x1,y1,x2,y2;
cin >> x1 >> y1 >> x2 >> y2;
uni.push_back(y1);
uni.push_back(y2);
a[i] = {x1,x2,y1,y2};
}
sort(uni.begin()+1,uni.end());
uni.erase(unique(uni.begin()+1,uni.end()),uni.end());
int m = uni.size()-1;
vector<node> seg(4*m+1);
function<void(int,int,int)> build = [&](int rt,int l,int r){
if (l==r){
seg[rt].len = uni[l]-uni[l-1];
return;
}
int mid = l+r >> 1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
seg[rt].len = seg[rt<<1].len+seg[rt<<1|1].len;
};
function<void(int,int,int,int,int,int)> update_range = [&](int rt,int l,int r,int x,int y,int v){
if (r<x || l>y){
return;
}
if (x<=l && y>=r){
seg[rt].cnt += v;
if (seg[rt].cnt>0){
seg[rt].cover = seg[rt].len;
}
else{
if (l!=r) seg[rt].cover = seg[rt<<1].cover+seg[rt<<1|1].cover;
else seg[rt].cover = 0;
}
return;
}
int mid = l+r >> 1;
update_range(rt<<1,l,mid,x,y,v);
update_range(rt<<1|1,mid+1,r,x,y,v);
if (seg[rt].cnt>0){
seg[rt].cover = seg[rt].len;
}
else{
seg[rt].cover = seg[rt<<1].cover+seg[rt<<1|1].cover;
}
};
build(1,1,m);
vector<array<ll,4>> wait;
for (int i=0;i<n;i++){
auto& [x1,x2,y1,y2] = a[i];
wait.push_back({x1,y1,y2,0});
wait.push_back({x2,y1,y2,1});
}
sort(wait.begin(),wait.end());
ll res = 0;
ll pre = INF;
for (auto& [x,y1,y2,op]:wait){
if (pre==INF){
pre = x;
}
res += (x-pre)*seg[1].cover;
int p1 = lower_bound(uni.begin()+1,uni.end(),y1)-uni.begin();
int p2 = lower_bound(uni.begin()+1,uni.end(),y2)-uni.begin();
update_range(1,1,m,p1+1,p2,op==0?1:-1);
pre = x;
}
cout << res << '\n';
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t = 1;
// cin >> t;
while (t--) solve();
return 0;
}

浙公网安备 33010602011771号