题意:给n个矩形到一个平面上,求他们的总面积。
思路:将他们的x坐标从小到大排序,然后根据对于当前x坐标而言他们的y坐标区间进行相应的维护某些变化,这种解题思路就是扫描线。对于这题,我们要维护的是y区间的覆盖情况。
然后用覆盖的总长度去乘以当前两个x之间的距离,再全部加起来就是答案。对于如何去计算每一个x后的y区间覆盖情况,我们可以令(x1,y1,y2,1)表示左区间,(x2,y1,y2,-1)为右区间。因为
去累加的时候相当于在x2后面的就没覆盖到了。也就是说只有x1~x2的[y1,y2]区间被覆盖,还要维护个cnt表示被覆盖的次数。因为数据太大且为double记得离散化。
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<cstdio>
#include<cmath>
#define ll long long
#define lowbit(x) x&(-x)
using namespace std;
const int N=1000+10;
struct node{
double x,y1,y2;
int val;
node() {}
node(double x, double y1, double y2,int val){
this->x = x; this->val = val;
this->y1 = y1; this->y2 = y2;
}
bool operator <(const node &t)const {
return x<t.x;
}
};
struct Tree
{
int l;
int r;
double len;
int cnt;
} t[N*2];
vector<node> a;
vector<double> y;
int n;
void pushup(int p)
{
int l=t[p].l;
int r=t[p].r;
if(t[p].cnt>0)
{
t[p].len=y[r+1]-y[l];
}
else
{
t[p].len=t[p<<1].len+t[p<<1|1].len;
}
}
void build(int p,int l,int r)
{
t[p].l=l;
t[p].r=r;
t[p].cnt=t[p].len=0;
if(l==r)
return;
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
}
void update(int p,int l,int r,int val)
{
if(t[p].l>=l&&t[p].r<=r)
{
t[p].cnt+=val;
pushup(p);
return;
}
int mid=(t[p].l+t[p].r)>>1;
if(l<=mid)
update(p<<1,l,r,val);
if(r>mid)
update(p<<1|1,l,r,val);
pushup(p);
}
int main()
{
int k=1;
while(~scanf("%d",&n))
{
if(n==0)
break;
y.clear();
a.clear();
for(int i=0;i<n;i++)
{
double x1,x2,y1,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
y.push_back(y1);
y.push_back(y2);
a.push_back(node(x1,y2,y1,1));
a.push_back(node(x2,y2,y1,-1));
}
y.push_back(-1);
sort(a.begin(),a.end());
sort(y.begin(),y.end());
y.erase(unique(y.begin(),y.end()),y.end());
int m=y.size(),num=a.size();
build(1,0,m);
double ans = 0.0;
for(int i=0;i<num;i++)
{
int l=lower_bound(y.begin(),y.end(),a[i].y2)-y.begin();
int r=lower_bound(y.begin(),y.end(),a[i].y1) - y.begin()-1;
update(1,l,r,a[i].val);
ans+=t[1].len*(a[i+1].x-a[i].x);
}
printf("Test case #%d\n",k++);
printf("Total explored area: %.2lf\n\n",ans);
}
return 0;
}