HDU1542 扫描线(矩形面积并)

时间:2023-12-30 17:17:08

Atlantis

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 18275    Accepted Submission(s): 7409

Problem 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 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.

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.

Sample Input
2
10 10 20 20
15 15 25 25.5
0
Sample Output
Test case #1
Total explored area: 180.00

题意

  给出n个矩形的左下角和右上角的坐标,求矩形面积的并

解题思路

  离散化x轴,然后扫描线,具体实现看代码

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=+;
int cnt[maxn*],n;//记录某个区间的下底边比上底边多的个数
double sum[maxn*];//记录某个区间下底边比上底边多的个数总长度
double Hash[maxn];//对横坐标x离散化 struct node{
double l,r,h;
int f;
node(){}
node(double x1,double x2,double hh,int ff):l(x1),r(x2),h(hh),f(ff){}
bool operator<(const node &a)const{
return h<a.h;
}
}s[maxn*]; void init(){
memset(sum,,sizeof(sum));
memset(cnt,,sizeof(cnt));
} void pushup(int x,int l,int r){
if(cnt[x]) sum[x]=Hash[r+]-Hash[l];//表示该区间整个线段长度可作为底边
else if(l==r) sum[x]=;//叶子结点区间长度为0,则底边长度为0
else sum[x]=sum[x*]+sum[x*+];
} void update(int x,int L,int R,int f,int l,int r){
if(L<=l&&r<=R){
cnt[x]+=f;
pushup(x,l,r);
return ;
}
int mid=(l+r)/;
if(L<=mid) update(x*,L,R,f,l,mid);
if(R>mid) update(x*+,L,R,f,mid+,r);
pushup(x,l,r);
} int main(){
double x1,x2,y1,y2; int p=;
while(cin>>n&&n){
init();int k=;
while(n--){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
if(x1>x2) swap(x1,x2);
if(y1>y2) swap(y1,y2);
Hash[k]=x1;
s[k++]=node(x1,x2,y1,);
Hash[k]=x2;
s[k++]=node(x1,x2,y2,-);
}
sort(s,s+k);//把线段按高度h从小到大排序
sort(Hash,Hash+k);//把x坐标从小到大排序 int ans=unique(Hash,Hash+k)-Hash;//去重复端点
double SUM=;
printf("Test case #%d\n",++p);
for(int i=;i<k;i++){
int l=lower_bound(Hash,Hash+ans,s[i].l)-Hash;
int r=lower_bound(Hash,Hash+ans,s[i].r)-Hash;
update(,l,r-,s[i].f,,ans-);//扫描线段更新可用底边长
SUM+=sum[]*(s[i+].h-s[i].h);//新增加面积 }
printf("Total explored area: %.2f\n\n",SUM);
}
return ;
}