#include<stdio.h>
#include<algorithm>
using namespace std;
#define Max 2005
struct lnode//存放线段
{
double l,r,h;
int d;
}line[2*Max];
struct node//线段树
{
int l,r,flag;
double sum;
}tree[4*Max];
double X[4*Max];
int k;
bool cmp(lnode a,lnode b)
{
return a.h<b.h;//从小到大
}
void build(int step,int l,int r)
{
tree[step].l=l;
tree[step].r=r;
tree[step].flag=0;
tree[step].sum=0;
if(l+1==r)
{
return;
}
int mid=(l+r)>>1;
build(step<<1,l,mid);
build(step<<1|1,mid,r);
}
void updata(int step,int l,int r,int c)
{
if(l<=tree[step].l&&tree[step].r<=r)
{
tree[step].flag+=c;
if(tree[step].flag!=0)
{
tree[step].sum=X[tree[step].r]-X[tree[step].l];//说明此线段有被覆盖
}
else
{
tree[step].sum=tree[step<<1].sum+tree[step<<1|1].sum;//还要求左右孩子是否存在覆盖,故要合并左右孩子
}
return ;
}
int mid=(tree[step].l+tree[step].r)>>1;
if(mid<r)
{
updata(step<<1|1,l,r,c);
}
if(l<mid)
{
updata(step<<1,l,r,c);
}
if(tree[step].flag!=0)
{
tree[step].sum=X[tree[step].r]-X[tree[step].l];//说明此线段有被覆盖
}
else
{
tree[step].sum=tree[step<<1].sum+tree[step<<1|1].sum;//合并左右孩子
}
}
int search(double x)
{
int low,high;
int mid;
low=0;
high=k;
while(low<=high)
{
mid=(low+high)>>1;
if(X[mid]==x)
{
return mid;
}
else
if(X[mid]<x)
{
low=mid+1;
}
else
{
high=mid-1;
}
}
return -1;
}
int main()
{
//freopen("1.txt","r",stdin);
int n,i,t=1;
int m;
double a,b,c,d,sum;
while(scanf("%d",&n)&&n)
{
m=0;
while(n--)
{
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);//把矩形映射到X轴
line[m].l=a;
line[m].r=c;
line[m].h=b;
line[m].d=1;
X[m]=a;
m++;
line[m].l=a;
line[m].r=c;
line[m].h=d;
line[m].d=-1;
X[m]=c;
m++;
}
sort(X,X+m);
sort(line,line+m,cmp);
k=0;
for(i=1;i<m;i++)//去掉重复的点
{
if(X[i]!=X[k])
{
k++;
X[k]=X[i];
}
}
build(1,0,k);
sum=0;
for(i=0;i<m-1;i++)
{
int l,r;
l=search(line[i].l);//寻找“线段坐标”离散化后的坐标
r=search(line[i].r);
if(l<r)
{
updata(1,l,r,line[i].d);//更新线段 求矩形的长 tree[1].sum
}
sum+=tree[1].sum*(line[i+1].h-line[i].h);//面积=长*宽
}
printf("Test case #%d\n",t++);
printf("Total explored area: %.2f\n\n",sum);
}
return 0;
}
hdu 1542 Atlantis
最新推荐文章于 2024-08-17 03:33:08 发布