求 $n$ 个矩形的面积并
此问题可抽象出一个问题模型:
给一初始全 0 的序列 $\{a_i\}_{i=1}^n$,每次操作如下:给定区间 $[l,r]$,令 $a_i=a_i+1,\forall i\in [l,r]$ 或 $a_i=a_i-1,\forall i\in [l,r]$,修改后立即询问 $\#\{a_i|a_i>0,i\in[1,n]\}$,保证任一修改后 $a_i\ge 0,\forall i\in[1,n]$
查看代码
查看代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN=1e6+5; #define ls o<<1 #define rs o<<1|1 ll X[MAXN<<1]; // 横线 struct Line{ // 左右端点的横坐标,竖坐标 ll l,r,h; // 1 表示下底边,-1 表示上底边 int mark; // 按高度排序 bool operator < (const Line &rhs) const { return h<rhs.h; } }L[MAXN<<1]; // 线段树结点维护的信息 struct Info{ // 区间左右端点,该区间位于多少个矩形内(值为正时有贡献) int l,r,sum; // 该区间的可做底边的长度(sum 值为正的长度) ll len; }; struct SegmentTree{ Info t[MAXN<<2]; void Pull(int o){ int l=t[o].l,r=t[o].r; // 若非 0 则有贡献 if(t[o].sum){ t[o].len=X[r+1]-X[l]; } else{ t[o].len=t[ls].len+t[rs].len; } } void Build(int o,int l,int r){ t[o].l=l,t[o].r=r; t[o].len=0; t[o].sum=0; if(l==r){ return; } int mid=(l+r)>>1; Build(ls,l,mid); Build(rs,mid+1,r); return; } void Update(int o,int nl,int nr,int c){ int l=t[o].l,r=t[o].r; if(nl<=l&&r<=nr){ t[o].sum+=c; Pull(o); return; } int mid=(l+r)>>1; if(nl<=mid) Update(ls,nl,nr,c); if(nr>mid) Update(rs,nl,nr,c); Pull(o); } }tree; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin>>n; for(int i=1;i<=n;i++){ ll X1,X2,Y1,Y2; cin>>X1>>Y1>>X2>>Y2; X[2*i-1]=X1,X[2*i]=X2; L[2*i-1]=(Line){X1,X2,Y1,1}; L[2*i]=(Line){X1,X2,Y2,-1}; } n<<=1; sort(L+1,L+n+1); sort(X+1,X+n+1); int tot=unique(X+1,X+n+1)-X-1; tree.Build(1,1,tot-1); ll ans=0; for(int i=1;i<n;i++){ int nl,nr; nl=lower_bound(X+1,X+tot+1,L[i].l)-X; nr=lower_bound(X+1,X+tot+1,L[i].r)-X-1; tree.Update(1,nl,nr,L[i].mark); ans+=tree.t[1].len*(L[i+1].h-L[i].h); } cout<<ans; return 0; }