//考察:线段树+离散化+扫描线
//PE 一次,最后还要再输出一个空行
#include<iostream>
#include<algorithm>
using namespace std;
struct seg{
double x,y1,y2;
int flag;//加入矩形最开始那条边为+1,加入矩形对边的时候为-1
seg(double a,double b,double c,int d):x(a),y1(b),y2(c),flag(d){}
seg(){};
};
seg line[205];
int cmp(seg a,seg b){
return a.x<b.x;
}
struct Node{
int l,r;
double yl,yr;
//cover这个变量很有用,每当加入矩形的一条对边时候,实际上是将该线段抹掉了
//所以只有当cover>0的时候,才能说明该段线段被覆盖了
int cover;
Node(int a,int b,double l,double r,int cv,double len):l(a),r(b),yl(l),yr(r),cover(cv){}
Node(){}
};
Node tree[205*4];
double y[205];
void build(int root,int l,int r){
//y的用途在这儿
tree[root]=Node(l,r,y[l],y[r],0);
int mid=(l+r)>>1;
if(l+1==r)
return;
build(root*2,l,mid);
build(root*2+1,mid,r);
}
//插入线段,注意flag的修改
void insert(int root,seg b){
if(b.y2<=tree[root].yl||b.y1>=tree[root].yr)
return;
if(b.y1<=tree[root].yl&&b.y2>=tree[root].yr){
tree[root].cover+=b.flag;
return;
}
insert(root*2,b);
insert(root*2+1,b);
}
double ss;
void Count(int root){
if(tree[root].cover>0){
ss+=(tree[root].yr-tree[root].yl);
return;
}
if(tree[root].r-tree[root].l==1)
return;
Count(root*2);
Count(root*2+1);
}
int n;
double x1,x2,y1,y2;
int main(){
int cases=0;
while(scanf("%d",&n)!=EOF&&n){
cases++;
int m=0;
while(n--){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
line[++m]=seg(x1,y1,y2,1);y[m]=y1;
line[++m]=seg(x2,y1,y2,-1);y[m]=y2;
}
//离散化
sort(line+1,line+1+m,cmp);sort(y+1,y+1+m);
build(1,1,m);
double sum=0;
for(int i=1;i<m;i++){
insert(1,line[i]);
ss=0;
Count(1);
sum+=ss*(line[i+1].x-line[i].x);
}
printf("Test case #%d\n",cases);
printf("Total explored area: %.2lf\n",sum);
printf("\n");
}
return 0;
}
POJ 1151 扫描线+线段树+离散化
最新推荐文章于 2022-03-08 17:29:18 发布