hdu 1542 Atlantis(线段树,扫描线)

来源:互联网 发布:环球人物和看天下知乎 编辑:程序博客网 时间:2024/05/16 15:51

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542

题意:n个矩阵,给出每个矩阵的左下和右上两个点的坐标,求出所有矩形总的覆盖面积。


扫描线问题,因为坐标是浮点型,那就必须把坐标离散化,我这直接上map了。

再来就是求这个面积的方式了:我这是向y轴映射,那么就保存每一条竖线,包扩该条竖线的x坐标,上下两个y坐标,还有用lr保存这条竖线是左边(1)那条还是右边(-1)那条,然后将所有的竖边按x从小到大排序,再一条一条地插入。看图:


先插入第一条竖边A1A2,再查询整棵数被覆盖的长度dy(即求出y坐标之差),这时候dy*(下一条边的x-插入这的条边的x)就等于第一部分的面积,以此类推。

插入A1A2可以求第一部分面积

插入B1B2可以求第二部分面积

插入C1C2可以求第三部分面积

最后一条不用插入

还有用1和-1标识左右边在这里也能看出来,当插入C1C2的时候,-1和插入A1A2时的1相抵消,表示这个区间不再覆盖,就避免了后面再计算时错误判断dy的值。

代码:

#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>#include<map>#define MAXN 1050using namespace std;struct ele{double x,yu,yd;int lr;bool operator < (ele t) const{return x<t.x;}}a[MAXN*2];struct node{int l,r;int cover;}t[MAXN*5];double yy[MAXN*2];void construct(int l,int r,int p){t[p].l=l,t[p].r=r,t[p].cover=0;if(r-l<=1) return ;int m=(l+r)>>1;construct(l,m,p*2);construct(m,r,p*2+1);}void modify(int l,int r,int val,int p){if(t[p].l==l&&t[p].r==r){t[p].cover+=val;return ;}int m=(t[p].l+t[p].r)>>1;if(r<=m)modify(l,r,val,p*2);else if(l>=m)modify(l,r,val,p*2+1);else{modify(l,m,val,p*2);modify(m,r,val,p*2+1);}}void query(double &ans,int p){if(t[p].cover){ans+=yy[t[p].r]-yy[t[p].l];return ;}else if(t[p].r-t[p].l>=1){t[p*2].cover+=t[p].cover,t[p*2+1].cover+=t[p].cover;query(ans,p*2);query(ans,p*2+1);t[p*2].cover-=t[p].cover,t[p*2+1].cover-=t[p].cover;}}int main(){int n,i,j,cas=1;double x1,x2,y1,y2;map<double,int> hash;while(scanf("%d",&n)&&n){for(i=1,j=1;i<=n;i++,j+=2){scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);a[j].x=x1,a[j].yd=y1,a[j].yu=y2;a[j].lr=1;a[j+1].x=x2,a[j+1].yd=y1,a[j+1].yu=y2;a[j+1].lr=-1;yy[j]=y1,yy[j+1]=y2;}sort(a+1,a+1+n*2);sort(yy+1,yy+1+2*n);int up=unique(yy+1,yy+1+2*n)-yy-1;for(i=1;i<=up;i++)hash[yy[i]]=i;double res=0,dy;construct(1,up,1);for(i=1;i<2*n;i++){dy=0;modify(hash[a[i].yd],hash[a[i].yu],a[i].lr,1);query(dy,1);res+=dy*(a[i+1].x-a[i].x);}printf("Test case #%d\n",cas++);printf("Total explored area: %.2lf\n\n",res);}return 0;}


原创粉丝点击