#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=210;
struct node{
int left,right,c; //c : 区间被覆盖的层数, m: 区间的测度
double m;
}tree[N*4];
struct Line{
double x,y1,y2; //纵方向直线, x:直线横坐标, y1 y2:直线上的下面与上面的两个纵坐标
int s; //s = 1 : 直线为矩形的左边, s = 0:直线为矩形的右边
}line[N];
bool cmp(Line a,Line b){
return a.x<b.x;
}
double ty[N],y[N]; //y[] 整数与浮点数的对应数组; ty[]:用来求y[]的辅助数组
void build(int t,int left,int right){
tree[t].left=left;
tree[t].right=right;
tree[t].c=0;
tree[t].m=0;
if(left+1<right){
int mid=(left+right)>>1;
build(t<<1,left,mid);
build((t<<1)+1,mid,right);
}
}
void update(int t){
if(tree[t].c>0) tree[t].m=y[tree[t].right]-y[tree[t].left];
//将线段树上区间的端点分别映射到 y[]数组所对应的浮点数上,由此计算出测度
else if(tree[t].left+1==tree[t].right) tree[t].m=0;
else tree[t].m=tree[t<<1].m+tree[(t<<1)+1].m;
}
void insert(int t,int left,int right){
if(left<=tree[t].left && tree[t].right<=right){
tree[t].c++;
update(t);
return ;
}
int mid=(tree[t].left+tree[t].right)>>1;
if(left<mid) insert(t<<1,left,right);
if(right>mid) insert((t<<1)+1,left,right);
update(t);
}
void del(int t,int left,int right){
if(left<=tree[t].left && tree[t].right<=right){
tree[t].c--;
update(t);
return ;
}
int mid=(tree[t].left+tree[t].right)>>1;
if(left<mid) del(t<<1,left,right);
if(right>mid) del((t<<1)+1,left,right);
update(t);
}
int getindex(int n,double x){//二分查找出浮点数 t 在数组y[]中的位置(此即所谓的映射关系)
int left,right,mid;
left=1;right=n;
while(left<=right){
mid=(left+right)>>1;
if(y[mid]<x) left=mid+1;
else right=mid-1;
}
return left;
}
int main(){
int n,i;
double x1,y1,x2,y2;
int cas=1;
while(scanf("%d",&n)!=EOF){
if(n==0) break;
for(i=0;i<n;i++){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
line[i*2].x=x1; line[i*2].y1=y1; line[i*2].y2=y2; line[i*2].s=1;
line[i*2+1].x=x2; line[i*2+1].y1=y1; line[i*2+1].y2=y2; line[i*2+1].s=0;
ty[i*2]=y1;ty[i*2+1]=y2;
}
n<<=1;
sort(line,line+n,cmp);
sort(ty,ty+n); //默认升序排序
int num=1;
y[1]=ty[0];
for(i=1;i<n;i++){ //离散化处理数组 ty[]使之不含重覆元素,得到新的数组存放到数组y[]中
if(ty[i]!=ty[i-1]) y[++num]=ty[i];
}
build(1,1,num);//树的叶子节点与数组 y[]中的元素个数相同,以便建立一一对应的关系
int left,right;
double ans=0;
for(i=0;i<n-1;i++){
left=getindex(num,line[i].y1); //由对应关系计算出线段两端在树中的位置
right=getindex(num,line[i].y2);
if(line[i].s==1) //插入矩形的左边
insert(1,left,right);
else //删除矩形的右边
del(1,left,right);
ans+=tree[1].m*(line[i+1].x-line[i].x);
}
printf("Test case #%d\n",cas++);
printf("Total explored area: %.2lf\n\n",ans);
}
return 0;
}
代码转自:http://www.cnblogs.com/CXCXCXC/p/5003389.html(poj1151)
本文介绍了一种使用线段树解决矩形面积并计算的方法。通过离散化处理和二分查找实现高效的区间覆盖更新与测度计算。适用于解决如POJ 1151等问题。
4730

被折叠的 条评论
为什么被折叠?



