扫描线的做法。
先对x坐标离散化,对离散化后的数组用线段树维护当前的边长。
最后要考虑到,线段树递归后的合并会出现两段之间的空缺,要把每个点和他到右面邻点的距离看成是一个点。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100010
struct seg{
double l,r,h;
int f;
bool operator < (const seg &a)const{
return h<a.h;
}
}t[N];
struct tree{
int cnt;
double len;
}e[N<<2];
double X[N];
int q=1;
void pushdown(int l,int r,int rt){
if(e[rt].cnt)
e[rt].len=X[r+1]-X[l];
else if(l==r)
e[rt].len=0;
else
e[rt].len=e[rt<<1].len+e[rt<<1|1].len;
}
void update(int L,int R,int l,int r,int rt,int val){
if(L<=l&&r<=R){
e[rt].cnt+=val;
pushdown(l,r,rt);
return ;
}
int m=l+r>>1;
if(L<=m) update(L,R,l,m,rt<<1,val);
if(R>m) update(L,R,m+1,r,rt<<1|1,val);
pushdown(l,r,rt);
}
int main()
{
int n;
double a,b,c,d;
while(cin>>n,n){
memset(t,0,sizeof(t));
int num=0;
for(int i=0;i<n;i++){
cin>>a>>b>>c>>d;
X[num]=a;
t[num++]={a,c,b,1};
X[num]=c;
t[num++]={a,c,d,-1};
}
sort(X,X+num);//离散化x坐标
sort(t,t+num);
int m=unique(X,X+num)-X;
double ans=0;
for(int i=0;i<num;i++){
int l=lower_bound(X,X+m,t[i].l)-X;
int r=lower_bound(X,X+m,t[i].r)-X-1;//当前x的区间l->r
update(l,r,0,m,1,t[i].f);//向0->m的线段树上插入l->r的t[i].f
ans+=e[1].len*(t[i+1].h-t[i].h);//底乘高
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n",q++,ans);
}
return 0;
}