问题描述
有几个古希腊文本包含了对传说中的亚特兰蒂斯岛的描述。其中一些文本甚至包括该岛部分地区的地图。但不幸的是,这些地图描述了亚特兰蒂斯的不同区域。你的朋友比尔必须知道地图存在的总面积。你(不明智地)自愿编写一个程序来计算这个数量。
输入
输入文件由几个测试用例组成。每个测试用例都以一行开始,其中包含一个可用映射的整数n (1<=n<=100)。下面的n行描述了每个映射。每一行包含四个数字x1、y1、x2、y2 (0<=x1<x2<=100000;0<=y1<y2<=100000),不一定是整数。的值(x1;y1)和(x2;y2)是左上角resp的坐标。地图区域的右下角。
输入文件被包含一个0的行终止。不处理它。
输出
对于每个测试用例,程序应该输出一个部分。每个部分的第一行必须测试案例# k, k是测试用例的数量(从1开始)。第二个必须“探索总面积:”,其中一个是总开发面积(即联盟的矩形的面积在本测试用例),印刷精确到小数点右边的两个数字。
在每个测试用例之后输出一个空行。
Sample Input
2
10 10 20 20
15 15 25 25.5
0
Sample Output
Test case #1
Total explored area: 180.00
分析:
个人觉得思路写的很清楚(不过代码就… ):konjak魔芋的博客
之前一直拖着没学扫描线,补一下。
因为数组下标不能是double所以用离散化搞成int
线段树维护底部扫描线长度和,乘上两条扫描线之间的距离差,累加至答案就行了
code:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
typedef long long ll;
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=205;
struct Line{
double l,r,h;
int f;
Line(){};
Line(double ll,double rr,double hh,int ff){
l=ll,r=rr,h=hh,f=ff;
}
}e[maxm<<2];
bool cmp(Line a,Line b){
return a.h<b.h;
}
struct Node{
int cnt;//表示覆盖了几次
double len;//长度
}a[maxm<<2];
double x[maxm<<2];
void pushup(int l,int r,int node){
if(a[node].cnt){//不为0说明全覆盖
a[node].len=x[r+1]-x[l];//用x数组更新长度
}else if(l==r){//如果是点就没有长度
a[node].len=0;
}else{//子节点长度和
a[node].len=a[node*2].len+a[node*2+1].len;
}
}
void update(int st,int ed,int l,int r,int node,int val){
if(st<=l&&ed>=r){
a[node].cnt+=val;
pushup(l,r,node);
return ;
}
int mid=(l+r)/2;
if(st<=mid){
update(st,ed,l,mid,node*2,val);
}
if(ed>=mid+1){
update(st,ed,mid+1,r,node*2+1,val);
}
pushup(l,r,node);
}
int main(){
int n;
int cas=1;
while(cin>>n&&n){
int cnt=0;
for(int i=0;i<n;i++){
double x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
x[cnt]=x1;
e[cnt++]=Line(x1,x2,y1,1);//下面的线
x[cnt]=x2;
e[cnt++]=Line(x1,x2,y2,-1);//上面的线
}
sort(x,x+cnt);
sort(e,e+cnt,cmp);
int m=unique(x,x+cnt)-x;
double ans=0;
// memset(a,0,sizeof a);//初始化树(因为树很小所以就不写build函数了)
// 如果下一行的循环条件是i<cnt-1就要用memset初始化一下
// 如果是i<cnt,最后一次update的时候会把所有都清零
for(int i=0;i<cnt;i++){
int l=lower_bound(x,x+m,e[i].l)-x;
int r=lower_bound(x,x+m,e[i].r)-x-1;//区间左闭右开,所以减1
update(l,r,0,m-1,1,e[i].f);
ans+=a[1].len*(e[i+1].h-e[i].h);
}
printf("Test case #%d\n",cas++);
printf("Total explored area: %.2f\n\n",ans);//不知道为啥自己电脑用lf会输出0但是提交能过,用f就没事
}
return 0;
}