题解:SP17123 IMBOX - Destroying the Weapon Warehouse
扫描线模板题。
双倍经验。
这题是最基础的矩形面积并题目。

像这样,把多个相交矩形转化成不相交的矩形面积和。
这些矩形的高很简单,所以我们现在考虑怎么计算长。
这时我们需要引入“入边”和“出边”的概念。
定义:在同一个矩形内,从下往上看,第一条看到的边为“入边”,第二条看到的边为“出边”。
图片来自OI WiKi。
从下往上,就是扫描线的方向。
当从下往上扫,遇到入边的线,则对入边区间扫到进行 \(+1\) 操作,遇到出边,那么对出边区间进行 \(-1\) 操作。
将上述的模型转成线段树就可以了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int ls(int p){
return p<<1;
}
int rs(int p){
return p<<1|1;
}
const int N=8000005;
int Tag[N];
int length[N];
int xx[N];
struct ScanLine{
int y;
int right_x,left_x;
int inout;
ScanLine(){}
ScanLine(int y,int x2,int x1,int io):
y(y),right_x(x2),left_x(x1),inout(io){}
} line[N];
bool cmp(ScanLine &a,ScanLine &b){
return a.y<b.y;
}
void pushup(int p,int pl,int pr){
if(Tag[p]) length[p]=xx[pr]-xx[pl];
else if(pl+1 == pr) length[p]=0;
else length[p]=length[ls(p)] + length[rs(p)];
}
void update(int L,int R,int io,int p,int pl,int pr){
if(L<=pl && pr<=R){
Tag[p] += io;
pushup(p,pl,pr);
return;
}
if(pl+1 == pr) return;
int mid=(pl+pr) >> 1;
if(L<=mid) update(L,R,io,ls(p),pl,mid);
if(R>mid) update(L,R,io,rs(p),mid,pr);
pushup(p,pl,pr);
}
signed main(){
int n;
cin>>n;
int cnt=0;
while(n--){
int x1,x2,y1,y2;
cin>>x1>>y1>>x2>>y2;
line[++cnt]=ScanLine(y1,x2,x1,1);
xx[cnt]=x1;
line[++cnt]=ScanLine(y2,x2,x1,-1);
xx[cnt]=x2;
}
sort(xx+1,xx+cnt+1);
sort(line+1,line+cnt+1,cmp);
int num=unique(xx+1,xx+cnt+1)-(xx+1);
memset(Tag,0,sizeof(Tag));
memset(length,0,sizeof(length));
int ans=0;
for(int i=1;i<=cnt;++i){
int L,R;
ans += length[1]*(line[i].y-line[i-1].y);
L=lower_bound(xx+1,xx+num+1,line[i].left_x)-xx;
R=lower_bound(xx+1,xx+num+1,line[i].right_x)-xx;
update(L,R,line[i].inout,1,1,num);
}
cout<<ans<<endl;
return 0;
}

浙公网安备 33010602011771号