分析:
1.矩形比较多,坐标也很大,所以横坐标需要离散化(纵坐标不需要)
2.重点:扫描线法:假想有一条扫描线,从左往右(从右往左),或者从下往上(从上往下)扫描过整个多边形(或者说畸形。。多个矩形叠加后的那个图形)。如果是竖直方向上扫描,则是离散化横坐标,如果是水平方向上扫描,则是离散化纵坐标。下面的分析都是离散化横坐标的,并且从下往上扫描的。
扫描之前还需要做一个工作,就是保存好所有矩形的上下边,并且按照它们所处的高度进行排序,另外如果是上边我们给他一个值-1,下边给他一个值1,我们用一个结构体来保存所有的上下边
struct segment
{
double l,r,h; //l,r表示这条上下边的左右坐标,h是这条边所处的高度
int f; //所赋的值,1或-1
}
接着扫描线从下往上扫描,每遇到一条上下边就停下来,将这条线段投影到总区间上(总区间就是整个多边形横跨的长度),这个投影对应的其实是个插入和删除线段操作。还记得给他们赋的值1或-1吗,下边是1,扫描到下边的话相当于往总区间插入一条线段,上边-1,扫描到上边相当于在总区间删除一条线段(如果说插入删除比较抽象,那么就直白说,扫描到下边,投影到总区间,对应的那一段的值都要增1,扫描到上边对应的那一段的值都要减1,如果总区间某一段的值为0,说明其实没有线段覆盖到它,为正数则有,那会不会为负数呢?是不可能的,可以自己思考一下)。
每扫描到一条上下边后并投影到总区间后,就判断总区间现在被覆盖的总长度,然后用下一条边的高度减去当前这条边的高度,乘上总区间被覆盖的长度,就能得到一块面积,并依此做下去,就能得到最后的面积
(这个过程其实一点都不难,只是看文字较难体会,建议纸上画图,一画即可明白,下面献上一图希望有帮组)
附上代码:
#include<bits/stdc++.h>
using namespace std;
#define MAXN 50004*2
struct node{
int l,r; //离散化后构建线段树的左右x坐标点位置
int cover; //用来记录重叠情况
double len,lf,rf; //len计算实在的长度,rf,lf对应真实数据
}segTree[MAXN<<2];
struct Line{
double y,x1,x2;
int f; //1表示入边,-1表示出边
}line[MAXN<<1];
bool cmp(Line a,Line b){
return a.y<b.y;
}
double x[MAXN<<1];
void build(int t,int l,int r){
segTree[t].l=l;segTree[t].r=r;
segTree[t].len=segTree[t].cover=0;
segTree[t].lf=x[l];
segTree[t].rf=x[r];
if(l+1==r){
return;
}
int mid=l+r>>1;
build(t<<1,l,mid);
build(t<<1|1,mid,r);
}
void cal_len(int t){//计算长度
if(segTree[t].cover>0){
segTree[t].len=segTree[t].rf-segTree[t].lf;
return ;
}
if(segTree[t].l+1==segTree[t].r){
segTree[t].len=0;
}else{
segTree[t].len=segTree[t<<1].len+segTree[t<<1|1].len;
}
}
void update(int t,Line e){ //加入线段e后更新线段树
if(e.x1==segTree[t].lf&&e.x2==segTree[t].rf){
segTree[t].cover+=e.f;
cal_len(t);
return;
}
if(e.x2<=segTree[t<<1].rf){
update(t<<1,e);
}else if(e.x1>=segTree[t<<1|1].lf){
update(t<<1|1,e);
}else{
Line tmp=e;
tmp.x2=segTree[t<<1].rf;
update(t<<1,tmp);
tmp=e;
tmp.x1=segTree[t<<1|1].lf;
update(t<<1|1,tmp);
}
cal_len(t);
}
int main(){
int i,n,t;
double x1,x2,y1,y2;
while(scanf("%d",&n)!=EOF){
t=1;
for(int i=1;i<=n;i++){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
line[t].y=y1;
line[t].x1=x1;
line[t].x2=x2;
line[t].f=1;
x[t]=x1;
t++;
line[t].y=y2;
line[t].x1=x1;
line[t].x2=x2;
line[t].f=-1;
x[t]=x2;
t++;
}
sort(line+1,line+t,cmp);
sort(x+1,x+t);
int len=unique(x+1,x+t)-x;
build(1,1,len-1);
update(1,line[1]);
double res=0;
for(int i=2;i<t;i++){
res+=segTree[1].len*(line[i].y-line[i-1].y);
update(1,line[i]);
}
printf("%.0f\n",res);
}
return 0;
}