网上很多人都说这题很经典,值得做一做,可对于刚学线段树的Acmer似乎有难度,我也不列外,搜了很多人的结题报告,也没几个人说清楚,完全不会!
只好拿着别人代码来敲,一步一步理解。画了一张图。也让我知道什么是离散化,什么是扫描线。
这也就说明了每次扫描相邻的两条边,并计算出y,那么就需要更新边。这样就把矩形分割了。
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define M 202
struct node{
int l,r; //节点中区间的信息
int cover; //标记是否有覆盖,
double len,lf,rf;
}segtree[M*3];
struct Line{
double x,y1,y2;
int f;
void init(double a,double b,double c,int d){x=a,y1=b,y2=c,f=d;}
}line[M];
bool cmp(Line a,Line b){
return a.x<b.x;
}
double y[M];
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=y[l];
segtree[t].rf=y[r];
if(l+1==r) return ;
int mid=(l+r)>>1;
Build(t<<1,l,mid);
Build(t<<1|1,mid,r);
}
void calc(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)
{
if(e.y1==segtree[t].lf&&e.y2==segtree[t].rf){
segtree[t].cover+=e.f;
calc(t);
return;
}
if(e.y2<=segtree[t<<1].rf) update(t<<1,e);
else if(e.y1>=segtree[t<<1|1].lf) update(t<<1|1,e);
else{
Line tmp=e;
tmp.y2=segtree[t<<1].rf;
update(t<<1,tmp);
tmp=e;
tmp.y1=segtree[t<<1|1].lf;
update(t<<1|1,tmp);
}
calc(t);
}
int main()
{
int i,n,t,cas=0;
double x1,y1,x2,y2;
while(scanf("%d",&n),n){
cas++;
t=1;
for(i=1;i<=n;i++){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
line[t].init(x1,y1,y2,1);
y[t++]=y1;
line[t].init(x2,y1,y2,-1);
y[t++]=y2;
}
sort(line+1,line+t,cmp);
sort(y+1,y+t);
Build(1,1,t-1);
update(1,line[1]);
double res=0;
for(i=2;i<t;i++){
res+=segtree[1].len*(line[i].x-line[i-1].x);
// printf("%lf %lf %lf#\n",segtree[1].len,line[i-1].x,line[i].x);
update(1,line[i]);
}
printf("Test case #%d\nTotal explored area: %.2f\n\n",cas,res);
}
}
/*
3
0 0 10 10
5 5 15 15
10 10 20 20
*/