题目链接:http://poj.org/problem?id=1151
算是模板题,做这个之前要搞懂离散化。这里,区间最好用[L,R),要不然有些区间无法计算得到。人比较懒,自己去琢磨,不写注释了QAQ。
#include <cstdio>
#include <vector>
#include <memory.h>
#include <algorithm>
#define maxn 110
using namespace std;
struct Line{
Line(int a,int b,double c,int d):left(a),right(b),y(c),weight(d){}
Line(){}
int left,right,weight;
double y;
friend bool operator<(Line p,Line q){
return p.y<q.y;
}
};
struct Rect{
double x1,y1,x2,y2;
}Data[maxn];
struct Node{
int left,right;
int cover;
}de[8*maxn];
vector<double>Map;
vector<Line>line;
int n;
void BuildTree(int i,int left,int right)
{ if(left>=right) return;
de[i].left=left;
de[i].right=right;
de[i].cover=0;
if(left==right-1) return;
int mid=(left+right)>>1;
BuildTree(2*i,left,mid);
BuildTree(2*i+1,mid,right);
}
void PushDown(int i)
{ if(de[i].left!=de[i].right&&de[i].cover!=-2)
{ de[2*i].cover=de[2*i+1].cover=de[i].cover;
de[i].cover=-2;
}
}
void AddQuery(int i,int left,int right,int cover)
{ if(left>=right) return;
if(left<=de[i].left&&de[i].right<=right&&de[i].cover!=-2)
{ de[i].cover+=cover;
return;
}
if(de[i].left==de[i].right-1) return;
PushDown(i);
int mid=(de[i].left+de[i].right)>>1;
if(right<mid) AddQuery(2*i,left,right,cover);
else if(left>=mid) AddQuery(2*i+1,left,right,cover);
else
{ AddQuery(2*i,left,mid,cover);
AddQuery(2*i+1,mid,right,cover);
}
}
double GetArea(int i,int left,int right,double height)
{ if(left>=right) return 0;
if(de[i].cover>=1)
{ int x=de[i].left,y=de[i].right;
return height*(Map[y]-Map[x]);
}
if(de[i].left==de[i].right-1) return 0;
int mid=(de[i].left+de[i].right)>>1;
if(right<mid) return GetArea(2*i,left,right,height);
else if(left>=mid) return GetArea(2*i+1,left,right,height);
else
{ double sum=0;
sum+=GetArea(2*i,left,mid,height);
sum+=GetArea(2*i+1,mid,right,height);
return sum;
}
}
void DiscretSolve()
{ int i,x,y;
sort(Map.begin(),Map.end());
Map.erase(unique(Map.begin(),Map.end()),Map.end());
for(i=0;i<n;++i)
{ x=lower_bound(Map.begin(),Map.end(),Data[i].x1)-Map.begin();
y=lower_bound(Map.begin(),Map.end(),Data[i].x2)-Map.begin();
line.push_back(Line(x,y,Data[i].y1,1));
line.push_back(Line(x,y,Data[i].y2,-1));
}
sort(line.begin(),line.end());
BuildTree(1,0,Map.size()-1);
}
void AreaUnion()
{ int i;
double ans=0;
AddQuery(1,line[0].left,line[0].right,line[0].weight);
for(i=1;i<line.size();++i)
{ ans+=GetArea(1,0,Map.size()-1,line[i].y-line[i-1].y);
AddQuery(1,line[i].left,line[i].right,line[i].weight);
}
printf("Total explored area: %.2lf\n",ans);
}
int main()
{ int i,len=1;
double a,b,c,d;
while(~scanf("%d",&n))
{ if(!n) break;
Map.clear();
line.clear();
for(i=0;i<n;++i)
{ scanf("%lf%lf%lf%lf",&Data[i].x1,&Data[i].y1,&Data[i].x2,&Data[i].y2);
Map.push_back(Data[i].x1);
Map.push_back(Data[i].x2);
}
DiscretSolve();
printf("Test case #%d\n",len++);
AreaUnion();
puts("");
}
return 0;
}