版权声明:LeoJAM Presents https://blog.csdn.net/fcb_x/article/details/81943023
扫描线模板题
看来扫描线水平依旧不过硬
本质:求矩形的并
利用扫描线一段一段的扫
实现方式是线段树
注意发现区间是实数问题
离散化
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define lc (p<<1)
#define rc (p<<1|1)
const int N=2e4+1000;
int n;
double mmp[N<<1];
int cntmmp=0;
int tot=0;
struct Data{
double l,r,h;
int val;
}A[N<<1];
int cntdata=0;
bool cmp(Data A,Data B){
return A.h<B.h;
}
struct Segment_Tree{
struct Node{
int lson,rson,addlazy;
double len;
}T[N<<2];
inline void Clear(){
memset(T,0,sizeof(T));
}
inline void PushUp(int p){
if(T[p].addlazy){
T[p].len=(mmp[T[p].rson+1]-mmp[T[p].lson]);
}
else{
if(T[p].lson==T[p].rson){
T[p].len=0;
}
else T[p].len=T[lc].len+T[rc].len;
}
}
inline void build(int p,int l,int r){
T[p].lson=l;
T[p].rson=r;
if(l==r){
T[p].len=T[p].addlazy=0;
return;
}
int mid=(l+r)/2;
build(lc,l ,mid);
build(rc,mid+1,r );
}
inline void Update(int p,int l,int r,int val){
if(l<=T[p].lson&&T[p].rson<=r){
T[p].addlazy+=val;
PushUp(p);
return;
}
int mid=(T[p].lson+T[p].rson)/2;
if(l<=mid)Update(lc,l,r,val);
if(mid <r)Update(rc,l,r,val);
PushUp(p);
}
}Tree;
int main(){
// freopen("test.in","r",stdin);
int Id=0;
while(~scanf("%d",&n)){
if(n==0)break;
Tree.Clear();
cntdata=cntmmp=0;
tot=0;
for(int i=1;i<=n;i++){
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
Data Add,Del;
Add.l=Del.l=x1;
Add.r=Del.r=x2;
Add.h=y1;
Del.h=y2;
Add.val=1;
Del.val=-1;
A[++cntdata]=Add;
A[++cntdata]=Del;
mmp[++cntmmp]=x1;
mmp[++cntmmp]=x2;
}
sort(A+1,A+1+cntdata,cmp);
sort(mmp+1,mmp+1+cntmmp);
int len=unique(mmp+1,mmp+1+cntmmp)-mmp-1;
Tree.build(1,1,len);
double ans=0;
for(int i=1;i<=cntdata;i++){
int l=lower_bound(mmp+1,mmp+1+len,A[i].l)-mmp;
int r=lower_bound(mmp+1,mmp+1+len,A[i].r)-mmp-1;
Tree.Update(1,l,r,A[i].val);
ans+=(A[i+1].h-A[i].h)*Tree.T[1].len;
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n",++Id , ans);
}
}