HDU 1542 Atlantis [离散化 + 扫描线 + 线段树]
http://acm.hdu.edu.cn/showproblem.php?pid=1542
给定平面上若干矩形,求出被这些矩形覆盖的区域的面积。
对所有矩形的
要高效的维护区间信息,首先想到的是线段树。然后,如果该边是“入边”,则将此边加到线段树中,否则,线段树中一定维护着这条边对应的“入边”,将它删除掉。
对于每一条“入边”,在遇到它所对应的“出边”之前,它都会影响着右边的面积,所有这些“入边”的并就是它们共同产生的影响。只要在下一条边加入之前统计出当前这部分的面积,那扫描完所有边后被这些矩形覆盖的面积就计算出来了。
还有一个问题。普通的线段树都是顶点式的,而这里要的是坐标区间式的。这有两种方法解决,一种是改变结点的闭合方式,如左闭右开,结点
#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-9;
#define rep(i,f,t) for(int i = (f),_end = (t); i <= _end; ++i)
#define clr(c,x) memset(c,x,sizeof(c));
#define MID int mid = (L+R)>>1;
#define CHD int lc = node<<1,rc = node<<1|1;
struct Node{
double x,y1,y2;
int from,to;
bool flag;
Node(double xx,double yy1,double yy2,bool f)
:x(xx),y1(yy1),y2(yy2),flag(f){}
bool operator< (const Node &n2) const{ return x < n2.x; }
};
vector<double> vs;
vector<Node> line;
const int maxn = 202<<2;
struct sgt{
int cov[maxn];
double len[maxn];
void init(){
clr(cov,0);
clr(len,0);
}
void maintain(int node,int L,int R){
if(cov[node]){
len[node] = vs[R]-vs[L-1];
}else if(L != R){
CHD;
len[node] = len[lc]+len[rc];
}else{
len[node] = 0;
}
}
double query(){
return len[1];
}
void update(int from,int to,int val,int node,int L,int R){
if(from <= L && R <= to){
cov[node] += val;
}else{
MID;CHD;
if(from <= mid)update(from,to,val,lc,L,mid);
if(to > mid) update(from,to,val,rc,mid+1,R);
}
maintain(node,L,R);
}
}tree;
bool equ(double x,double y){
return fabs(x-y)<eps;
}
bool cmp(double x,double y){
if(equ(x,y))return false;
return x < y;
}
void pre(){
sort(vs.begin(),vs.end());
vs.erase(unique(vs.begin(),vs.end(),equ),vs.end());
rep(i,0,line.size()-1){
line[i].from = lower_bound(vs.begin(),vs.end(),line[i].y1,cmp) - vs.begin();
line[i].to = lower_bound(vs.begin(),vs.end(),line[i].y2,cmp) - vs.begin();
}
sort(line.begin(),line.end());
}
int main(){
int n;
int cas = 0;
while(scanf("%d",&n), n){
tree.init();
line.clear();
vs.clear();
rep(i,1,n){
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
vs.push_back(y1);
vs.push_back(y2);
line.push_back(Node(x1,y1,y2,true));
line.push_back(Node(x2,y1,y2,false));
}
pre();
double x = 0;
double ans = 0;
rep(i,0,line.size()-1){
double len = line[i].x-x;
ans += len*tree.query();
x = line[i].x;
int v = (line[i].flag?1:-1);
tree.update(line[i].from+1,line[i].to,v,1,1,line.size()-1);
}
printf("Test case #%d\n",++cas);
printf("Total explored area: %.2lf\n\n",ans);
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。