Atlantis
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 17858 | Accepted: 6796 |
Description
There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the island. But unfortunately, these maps describe different regions of Atlantis. Your friend Bill has to know the total area for which maps exist. You (unwisely) volunteered to write a program that calculates this quantity.
Input
The input 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.
The input file is terminated by a line containing a single 0. Don't process it.
Output
For 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.
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
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct Line
{
double x,y1,y2; //y边上下端点及x值
int flag; //1记录入边,-1为出边
}line[210];
struct node //线段树节点
{
int l,r; //离散化后对应的左右端点
double lf,rf; //真实的左右端点值
int lc,rc; //线段树的左右孩子节点
int cover,len; //cover记录当前节点是否被完全覆盖,>0则是
}tree[100002];
int tr; //线段树节点个数
double y[210]; //用于离散化,即保存y各端点的真实值
void build(int l,int r) //在l~r区间建线段树
{
int now=++tr;
tree[now].l=l;
tree[now].r=r;
tree[now].lf=y[l];
tree[now].rf=y[r];
tree[now].cover=tree[now].len=tree[now].lc=tree[now].rc=0;
if(l+1<r)
{
tree[now].lc=tr+1;
build(l,(l+r)/2);
tree[now].rc=tr+1;
build((l+r)/2,r);
}
}
double Count(int v) //统计在当前x区间扫过的矩形的y的长度的并
{ //即线段树当前cover>0的区域的并
if(tree[v].cover>0)
{
return (tree[v].rf-tree[v].lf);
}
if(tree[v].l+1==tree[v].r) return 0;
else return (Count(tree[v].lc)+Count(tree[v].rc));
}
void insert(int v,Line a)//将边a插入线段树
{
if(tree[v].lf==a.y1 && tree[v].rf==a.y2)
{
tree[v].cover+=a.flag;
//Count(v);
return;
}
if(tree[tree[v].lc].rf>=a.y2) insert(tree[v].lc,a);
else if(tree[tree[v].rc].lf<=a.y1) insert(tree[v].rc,a);
else{
Line x=a;
x.y1=tree[tree[v].rc].lf;
insert(tree[v].rc,x);
x=a;
x.y2=tree[tree[v].lc].rf;
insert(tree[v].lc,x);
}
//Count(v);
}
bool cmp(Line a,Line b)
{
return a.x<b.x;
}
int main()
{
int t=0;
int n,ln,yn;
double x1,x2,y1,y2;
while(scanf("%d",&n)&&n)
{
ln=tr=yn=0;
printf("Test case #%d\n",++t);
for(int i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
line[++ln].x=x1;line[ln].y1=y1;line[ln].y2=y2;line[ln].flag=1;
line[++ln].x=x2;line[ln].y1=y1;line[ln].y2=y2;line[ln].flag=-1;
y[++yn]=y1;
y[++yn]=y2;
}
sort(line+1,line+1+ln,cmp);
sort(y+1,y+1+yn);
build(1,yn);
insert(1,line[1]);
double sum=0;
for(int j=2;j<=n*2;j++)//扫描线思想
{
sum+=Count(1)*(line[j].x-line[j-1].x);
insert(1,line[j]);
}
printf("Total explored area: %.2lf\n",sum);
printf("\n");
}
return 0;
}