POJ 1151 Atlantis (线段树+扫描线 求矩形面积并)
2015-05-14 20:08
399 查看
经典扫描线题,算法网上有很详细的,这里简单说一下:
把每个矩形拆成两条竖边,标记每条边是左边的还是右边的,把所有的边按x坐标排序。用一个数组cov标记整个y轴每个部分在多少个矩形中,哪些不是。把浮点数离散化。
然后开始扫描:先把答案加上(全部在矩形中的区间的长度和)×(这条边x坐标和前一条边x坐标之差),代表这两条边之间被覆盖的面积,然后这条边如果是左边,就把所覆盖区间的cov数组+1,是右边就-1.
区间加和查询用线段树实现,但是是一个特殊的线段树。
1.对于区间(l,r),它的子区间是(l,mid)和(mid,r)。
2.不需要lazy数组,因为查询的区间永远只有一个就是最大区间,所以更新某个区间后不需要更新它的子区间。
3.pushup时,如果cov[rt]大于0,长度就是整个区间,否则就是两个子区间长度和(不是0)
代码:
把每个矩形拆成两条竖边,标记每条边是左边的还是右边的,把所有的边按x坐标排序。用一个数组cov标记整个y轴每个部分在多少个矩形中,哪些不是。把浮点数离散化。
然后开始扫描:先把答案加上(全部在矩形中的区间的长度和)×(这条边x坐标和前一条边x坐标之差),代表这两条边之间被覆盖的面积,然后这条边如果是左边,就把所覆盖区间的cov数组+1,是右边就-1.
区间加和查询用线段树实现,但是是一个特殊的线段树。
1.对于区间(l,r),它的子区间是(l,mid)和(mid,r)。
2.不需要lazy数组,因为查询的区间永远只有一个就是最大区间,所以更新某个区间后不需要更新它的子区间。
3.pushup时,如果cov[rt]大于0,长度就是整个区间,否则就是两个子区间长度和(不是0)
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define lson l,mid,rt<<1 #define rson mid,r,rt<<1|1 using namespace std; #include <set> #include <map> set<double> Rem; map<double,int> Hash; double a[1000]; int cov[1000]; int N; struct line{ double x,iy1,iy2; int y1,y2; int c; }Line[205]; double Y[205]; bool cmp(line a,line b){ if(a.x==b.x) return a.c<b.c; return a.x<b.x; } void pushup(int l,int r,int rt){ if(cov[rt]>0) a[rt]=Y[r]-Y[l]; else a[rt]=a[rt<<1]+a[rt<<1|1]; } void update(int l,int r,int rt,int L,int R,int c){ if(l>=L&&r<=R){ cov[rt]+=c; pushup(l,r,rt); return ; } int mid=(l+r)/2; if(mid>L) update(lson,L,R,c); if(mid<R) update(rson,L,R,c); pushup(l,r,rt); } int main(){ int kase=1; while(~scanf("%d",&N)){ if(!N) break; memset(a,0,sizeof(a)); memset(cov,0,sizeof(cov)); memset(Y,0,sizeof(Y)); Rem.clear(); Hash.clear(); for(int i=0;i<N;i++){ double x1,x2,y1,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); Line[i].x=x1;Line[i].c=1; Line[i].iy1=y1;Line[i].iy2=y2; Line[i+N].x=x2;Line[i+N].c=-1; Line[i+N].iy1=y1;Line[i+N].iy2=y2; Rem.insert(y1);Rem.insert(y2); } set<double>::iterator p; int cnt=0; for(p=Rem.begin();p!=Rem.end();p++){ Hash[*p]=++cnt; Y[cnt]=*p; } sort(Line,Line+2*N,cmp); for(int i=0;i<N*2;i++){ Line[i].y1=Hash[Line[i].iy1]; Line[i].y2=Hash[Line[i].iy2]; } update(1,cnt,1,Line[0].y1,Line[0].y2,Line[0].c); double res=0; for(int i=1;i<2*N;i++){ res+=(Line[i].x-Line[i-1].x)*a[1]; update(1,cnt,1,Line[i].y1,Line[i].y2,Line[i].c); } printf("Test case #%d\n",kase++); printf("Total explored area: %.2f\n\n",res); } return 0; }
相关文章推荐
- hdu 1542 & poj 1151 Atlantis 线段树扫描线求矩形面积并
- poj 1151 Atlantis / hdu 1542 线段树扫描线 矩形面积并
- hdu 1542&&poj 1151 Atlantis[线段树+扫描线求矩形面积的并]
- POJ 1151Atlantis 矩形面积并[线段树 离散化 扫描线]
- POJ 1151 Atlantis(扫描线 + 线段树 矩形面积的并)
- 【线段树 + 离散化 + 扫描线】poj 1151 Atlantis 矩形面积并
- poj 1151 Atlantis (离散化 + 扫描线 + 线段树 矩形面积并)
- poj 1151 Atlantis(多矩形面积) + poj 1177Picture(多矩形周长) 线段树进阶
- POJ 1151 Atlantis 线段树求矩形面积并 方法详解
- poj 1151 Atlantis】线段树之扫描线(面积并)
- POJ 1151 Atlantis(线段树+扫描线+坐标离散求矩形面积并)
- POJ 1151 Atlantis 矩形切割 || 线段树 扫描线
- 扫描线——求矩形混合面积——poj 1151 Atlantis
- poj 1151-Atlantis线段树求矩形面积并解题报告
- POJ 1151 / HDU 1542 Atlantis 线段树求矩形面积并
- POJ 1151 Atlantis (线段树求矩形面积并)
- HDOJ 1542 (POJ 1151) Atlantis 【线段树 离散化 扫描线 面积并】
- POJ-1151-Atlantis(线段树+扫描线+离散化)[矩形面积并]
- POJ 1151 / HDU 1542 Atlantis 线段树求矩形面积并
- POJ 1151 Atlantis 矩形面积求交/线段树扫描线