InputThe input file consists of several test cases. Each test case starts with a line containing a single integer n (1<=n<=100) of available maps. The n following lines describe one map each. Each of these lines contains four numbers x1;y1;x2;y2 (0<=x1<x2<=100000;0<=y1<y2<=100000), not necessarily integers. The values (x1; y1) and (x2;y2) are the coordinates of the top-left resp. bottom-right corner of the mapped area.
The input file is terminated by a line containing a single 0. Don’t process it.OutputFor each test case, your program should output one section. The first line of each section must be “Test case #k”, where k is the number of the test case (starting with 1). The second one must be “Total explored area: a”, where a is the total explored area (i.e. the area of the union of all rectangles in this test case), printed exact to two digits to the right of the decimal point.
Output a blank line after each test case.
Sample Input
2
10 10 20 20
15 15 25 25.5
0
Sample Output
Test case #1
Total explored area: 180.00
题解:扫描线常规操作,如果不会先看大神的讲解再来:https://blog.csdn.net/xianpingping/article/details/83032798
#include<bits/stdc++.h>
using namespace std;
const int maxn=205;
double x[maxn];
struct node
{
double l,r,h;
int d;
bool operator < (const node &a)const//按纵坐标从小到大排序
{
return h<a.h;
}
}line[maxn];
int cnt[maxn<<2];//cnt[rt]表示该节点的覆盖次数,只要不为0就是被覆盖过
double sum[maxn<<2];//线段树sum[rt]中每一个节点都是一个区间,sum[rt]表示该节点区间中的总有效覆盖长度
double area;
void pushup(int l,int r,int rt)
{
if(cnt[rt])//如果该节点(就是一个区间)全部被覆盖,那么sum就是这个区间的长度了~
sum[rt]=x[r+1]-x[l];//x的下标是点,对于线段树的一个区间要进行右边下标+1再减去左边
else //否则要进行左右儿子的加和,因为不连续啊~
sum[rt]=sum[rt*2]+sum[rt*2+1];
}
void update(int L,int R,int v,int l,int r,int rt)//在L,R区间覆盖次数加上v,即如果v为1就加1,为-1就减1
{
if(L<=l&&R>=r)
{
cnt[rt]+=v;
pushup(l,r,rt);//改变了cnt数组后要重新pushup
return ;
}
int mid=(l+r)/2;//下面常规操作~
if(L<=mid)
update(L,R,v,l,mid,rt*2);
if(R>=mid+1)
update(L,R,v,mid+1,r,rt*2+1);
pushup(l,r,rt);
}
int main()
{
int t,k=1;
while(cin>>t&&t)
{
memset(cnt,0,sizeof(cnt));//初始化全部为0
memset(sum,0,sizeof(sum));
area=0; //求得面积
int n=0,m=0;//x数组得最大元素个数,line数组得最大元素个数
for(int i=1;i<=t;i++)//记录信息
{
double x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
x[++n]=x1;
x[++n]=x2;
line[++m]=(node){x1,x2,y1,1};
line[++m]=(node){x1,x2,y2,-1};
}
sort(x+1,x+1+n);//对x数组从小打大排序
sort(line+1,line+1+m);//对line扫描线数组按高度(即y)从小到大排序
int r=unique(x+1,x+1+n)-x-1;//r个不同的x将一条线段分成r-1个小区间,这也是后面查询总区长度是1到r-1和R--的原因
for(int i=1;i<m;i++)//这里是对扫描线进行扫描~,扫描m-1次即可
{
int L=lower_bound(x+1,x+r+1,line[i].l)-x;
int R=lower_bound(x+1,x+r+1,line[i].r)-x;
R--;//每一个节点是一个区间,这里是将点转化为区间的操作
update(L,R,line[i].d,1,r-1,1);
area+=sum[1]*(line[i+1].h-line[i].h);//用总有效长度乘上两条扫描线之间的距离即得到该块面积
}
printf("Test case #%d\nTotal explored area: %.2f\n\n",k++,area);
}
return 0;
}
来源:oschina
链接:https://my.oschina.net/u/4376386/blog/3606311