扫描线模板(矩形面积并)
首先离散化的思想,将各个线段细分到单位长,于是就是动态求当前值域内 tag \(> 1\) 的数量。
以下是参考代码,十分优美
int n, cnt;
ll xx[N];
struct Scanline{
ll y;
ll lx, rx;
int inout;
bool operator < (const Scanline &t) const{
return y < t.y;
}
}line[N];
void lineadd(ll yt, ll lxt, ll rxt, int inoutt, int count){
line[count].inout = inoutt;
line[count].y = yt;
line[count].lx = lxt;
line[count].rx = rxt;
}
int ls(int p){return p << 1;}
int rs(int p){return p << 1|1;}
struct SegmentTree{
ll tree[N << 2|1];
int tag[N << 2 |1];
inline void push_up(int p, int pl, int pr){
// 向上传递节点,更新节点值
if(tag[p]){
tree[p] = xx[pr] - xx[pl];
}else if(pl + 1 == pr){
tree[p] = 0;
}else{
tree[p] = tree[ls(p)] + tree[rs(p)];
}
}
inline void update(int L, int R, int p, int pl, int pr, int inoutt){
if(L <= pl && pr <= R){
tag[p] += inoutt;
push_up(p, pl, pr);
return ;
}
if(pl + 1 == pr) return ;
int mid = (pl + pr) >> 1;
if(L <= mid){
update(L, R, ls(p), pl, mid, inoutt);
}
if(R >= mid + 1){
update(L, R, rs(p), mid, pr, inoutt); // 注意不是 mid + 1,因为连续性
}
push_up(p, pl, pr);
}
};
SegmentTree seg;
void solve() {
cin >> n;
ll x1, x2, y1, y2;
for(int i = 1; i <= n; i++){
cin >> x1 >> y1 >> x2 >> y2;
lineadd(y1, x1, x2, 1, ++cnt);
xx[cnt] = x1;
lineadd(y2, x1, x2, -1, ++cnt);
xx[cnt] = x2;
}
sort(xx + 1, xx + 1 + cnt);
sort(line + 1, line + 1 + cnt);
int xlen = unique(xx + 1, xx + 1 + cnt) - (xx + 1);
ll ans = 0;
for(int i = 1; i <= cnt; i++){
ans += seg.tree[1]*(line[i].y - line[i - 1].y);
int L = lower_bound(xx + 1, xx + 1 + xlen, line[i].lx) - xx;
int R = lower_bound(xx + 1, xx + 1 + xlen, line[i].rx) - xx;
seg.update(L, R, 1, 1, xlen, line[i].inout);
}
cout << ans << "\n";
}
标签:cnt,int,ll,xx,扫描线,x2,line,矩形,模板
From: https://www.cnblogs.com/9102qyy/p/18449433