版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Lngxling/article/details/81325166
覆盖的面积
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 7404 Accepted Submission(s): 3732
Problem Description
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.
注意:本题的输入数据较多,推荐使用scanf读入数据.
Output
对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
Sample Input
2 5 1 1 4 2 1 3 3 7 2 1.5 5 4.5 3.5 1.25 7.5 4 6 3 10 7 3 0 0 1 1 1 0 2 1 2 0 3 1
Sample Output
7.63 0.00
思路:
扫描线,用线段树维护当前投影到x轴上的覆盖一次和两次的长度
大体不变,只要更改一下回溯的更新函数(代码里的up函数)
len1表示覆盖一次的长度,len2表示覆盖两次的长度,s表示覆盖的次数
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <vector>
#include <bitset>
#define max_ 1010
#define inf 0x3f3f3f3f
#define ll long long
#define les 1e-8
#define mod 364875103
using namespace std;
struct node
{
int l,r;
int s;
double len1,len2;
};
struct node tree[max_*8];
struct edge
{
double l,r;
double h;
int f;
bool operator < (const edge &a)const
{
return h<a.h;
}
};
struct edge e[max_*2];
int n;
double x[max_*2];
void built(int i,int l,int r)
{
tree[i].l=l;
tree[i].r=r;
tree[i].s=0;
tree[i].len1=tree[i].len2=0;
if(l+1==r)
return;
int mid=(l+r)>>1;
built(i<<1,l,mid);
built(i<<1|1,mid,r);
}
void up(int i)
{
if(tree[i].s>=2)
tree[i].len1=tree[i].len2=x[tree[i].r]-x[tree[i].l];
else if(tree[i].s==1)
{
tree[i].len1=x[tree[i].r]-x[tree[i].l];
if(tree[i].l+1==tree[i].r)
tree[i].len2=0;
else
tree[i].len2=tree[i<<1].len1+tree[i<<1|1].len1;
}
else
{
if(tree[i].l+1==tree[i].r)
{
tree[i].len1=tree[i].len2=0;
}
else
{
tree[i].len1=tree[i<<1].len1+tree[i<<1|1].len1;
tree[i].len2=tree[i<<1].len2+tree[i<<1|1].len2;
}
}
}
void updata(int i,int l,int r,int v)
{
if(tree[i].l==l&&tree[i].r==r)
{
tree[i].s+=v;
up(i);
return;
}
int mid=(tree[i].l+tree[i].r)>>1;
if(r<=mid)
updata(i<<1,l,r,v);
else if(l>=mid)
updata(i<<1|1,l,r,v);
else
{
updata(i<<1,l,mid,v);
updata(i<<1|1,mid,r,v);
}
up(i);
}
int main(int argc, char const *argv[]) {
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
double x1,x2,y1,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
int p=i*2-1;
int q=i*2;
e[p].l=e[q].l=x1;
e[p].r=e[q].r=x2;
e[p].h=y1;
e[q].h=y2;
e[p].f=1;
e[q].f=-1;
x[p]=x1;
x[q]=x2;
}
sort(x+1,x+1+2*n);
sort(e+1,e+1+2*n);
built(1,1,2*n);
double ans=0;
for(int i=1;i<2*n;i++)
{
int l=lower_bound(x+1,x+1+2*n,e[i].l)-x;
int r=lower_bound(x+1,x+1+2*n,e[i].r)-x;
updata(1,l,r,e[i].f);
ans+=tree[1].len2*(e[i+1].h-e[i].h);
}
printf("%.2f\n",ans);
}
return 0;
}