题意:给出n个矩形的 左下角和右上角坐标,计算他们覆盖的面积。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <string.h>
#include <map>
#include <set>
using namespace std;
#define maxn 11005
struct line
{
double x1,x2,y1;
int c;
line(){}
line(double xx1,double xx2,double yy1,int cc):
x1(xx1),x2(xx2),y1(yy1),c(cc){}
}s[maxn];//存平行于x轴的边,同时存下一个纵坐标,用于计算竖边长度
bool clm(line x,line y)
{
return x.y1<y.y1;
}
struct node
{
int l,r;
double len;//存某个区间覆盖的长度
int c;//c==1表示的某个线段区间完全覆盖,c==0表示不完全覆盖
}tree[maxn*4];
double x[maxn];
int n;
void build(int id,int l,int r)
{
tree[id].l=l;
tree[id].r=r;
tree[id].c=0;
tree[id].len=0.0;
if(l!=r)
{
int mid=(l+r)/2;
build(id*2,l,mid);
build(id*2+1,mid+1,r);
}
}
void pushup(int id,int l,int r)
{
if(tree[id].c>0)//tree[id].c>0该区间完全覆盖
tree[id].len=x[r]-x[l-1];
else if(l==r)tree[id].len=0.0;//在tree[id].c不大于0的情况下,l==r,自然覆盖为零
else//另外,在tree[id].c不大于0,就是它左右儿子的长度
tree[id].len=tree[id*2].len+tree[id*2+1].len;
}
void update(int id,int l,int r,int c)
{
if(l==tree[id].l&&tree[id].r==r)//注意这里要恰好要等于更新的区间
{
tree[id].c+=c;
pushup(id,tree[id].l,tree[id].r);
}
else
{
int mid=(tree[id].l+tree[id].r)/2;
if(r<=mid)update(id*2,l,r,c);//如果r<=mid,说明全在左边
else if(l>mid)update(id*2+1,l,r,c);//如果l>mid,说明全在右边
else
{
//这种情况就是左右边都有
update(id*2,l,mid,c);//我们更新的是l~mid
update(id*2+1,mid+1,r,c);//mid+1~r
}
pushup(id,tree[id].l,tree[id].r);
}
}
int main()
{
int i,k;
double x1,x2,y1,y2;
int tt=1;
while(cin>>n&&n)
{
k=0;
for(i=0;i<n;i++)
{
cin>>x1>>y1>>x2>>y2;
s[k]=line(x1,x2,y1,1);
x[k]=x1;
k++;
s[k]=line(x1,x2,y2,-1);
x[k]=x2;
k++;
}
sort(s,s+k,clm);//x的边按照高度排序
sort(x,x+k);//x数组存的是平行于x轴每边的横坐标,用于计算横边的长度(double型)
int m=1;
for(i=1;i<k;i++)
{
if(x[i]!=x[i-1])
x[m++]=x[i];
}//取出重合的横坐标
build(1,1,m-1);//按边建树
double ans=0.0;
for(i=0;i<k-1;i++)
{
int l=lower_bound(x,x+m-1,s[i].x1)-x;//查找s[i].x1,s[i].x2在x中的下标用于更新
int r=lower_bound(x,x+m-1,s[i].x2)-x;
update(1,l+1,r,s[i].c);
ans+=tree[1].len*(s[i+1].y1-s[i].y1);//每次更新后覆盖的总长度为tree[1].len
//再乘以相对高度就是面积
}
printf("Test case #%d\n",tt++);
printf("Total explored area: %0.2f\n",ans);
cout<<endl;
}
return 0;
}