线段树的扫描线
#include <iostream>
#include <cstdio>
#include <algorithm>
#define MAXN 2222
using namespace std;
struct line
{
double s,e,h,type;//记录的是每一条线的起点 终点 距离X周的面积
}L[MAXN]; //是底还是高 底是1高是-1 意味着底就是覆盖。高就是删除
double tree[MAXN<<2];
int cnt[MAXN<<2];
double X[MAXN<<2];
bool cmp(line a,line b)
{
return a.h<b.h;//按线的高度排序
}
void pushup(int num,int l,int r)
{
if(cnt[num])tree[num] = X[r+1] - X[l];//如果被完全覆盖
// else if(l==r)tree[num]=0;
else tree[num] = tree[num<<1] + tree[num<<1|1];//如果没有被完全覆盖
}
int bin(double tag,int top)//离散化二分找位置
{
int bo=0;
int to=top-1;
int mid;
while(bo<=to)
{
mid=(bo+to)>>1;
if(X[mid]==tag)return mid;
else if(X[mid]>tag)to=mid-1;
else bo=mid+1;
}
return -1;
}
void update(int num,int s,int e,int l,int r,int val)
{
if(l<=s && r>=e)
{
cnt[num]+=val;
pushup(num,s,e);//如果不要这句的话 自己这个节点就没有被更新了
return ;
}
int mid=(s+e)>>1;
if(l<=mid)update(num<<1,s,mid,l,r,val);
if(r>mid)update(num<<1|1,mid+1,e,l,r,val);
pushup(num,s,e);
}
int main()
{
int n;
int cas=1;
while(scanf("%d",&n)!=EOF && n)
{
int m=0;
while(n--)
{
double a,b,c,d;
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);//离散化
X[m]=a;
L[m].s=a;L[m].e=c;L[m].h=b;L[m++].type=1;
X[m]=c;
L[m].s=a;L[m].e=c;L[m].h=d;L[m++].type=-1;
}
sort(L,L+m,cmp);
sort(X,X+m);
int k=1;
for(int i=1;i<m;i++)
{
if(X[i]!=X[i-1])X[k++]=X[i];
}
memset(tree,0,sizeof(tree));
memset(cnt,0,sizeof(cnt));
double ans=0;
for(int i=0;i<m-1;i++)
{
int lef=bin(L[i].s,k);
int rig=bin(L[i].e,k)-1;
if(lef<=rig)update(1,0,k,lef,rig,L[i].type);
ans+=tree[1]*(L[i+1].h - L[i].h);
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n",cas++ , ans);
}
}