4837: Poj1151 Atlantis
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 21 Solved: 12
[Submit][Status][Web Board]
Description
给定平面直角坐标系中的N个矩形,求它们的面积并,即这些矩形的并集在坐标系中覆盖的总面积,如下图所示。
Input
Output
Sample Input
2
10 10 20 20
15 15 25 25.5
0
Sample Output
Test case #1
Total explored area: 180.00
HINT
Source
求矩形围成的面积,应用扫描线
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=1000+10; struct line{ int f; double x,y1,y2; }; struct node{ int l,r,c; double ly,ry,sum; }tree[maxn<<2];建树 int n; line l[maxn*2];存每条线, double Y[maxn*4];存下所有的纵坐标,以便建树,即用从小到大后用,纵坐标进行建树,则可以匹配 bool cmp(const line &a,const line &b){ return a.x<b.x; } void build(int rt,int l,int r){ tree[rt].l=l,tree[rt].r=r; tree[rt].sum=0; tree[rt].c=0; tree[rt].ly=Y[l]; tree[rt].ry=Y[r]; if(l+1==r) return ; int mid=(l+r)>>1; build(rt<<1,l,mid); build(rt<<1|1,mid,r);建树操作,具体为什么是mid,我也不晓得,记得就好了 } void calc(int rt){ if(tree[rt].c>0) tree[rt].sum=tree[rt].ry-tree[rt].ly;如果此线被多次覆盖,那么此线长度为该点坐标之差 else if(tree[rt].l+1==tree[rt].r) tree[rt].sum=0;若线段为点长度为0 else tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;若不满足以上条件则线段长度从子节点中统计 } void update(int rt,line e){ if(e.y1==tree[rt].ly&&e.y2==tree[rt].ry){找到两个纵坐标端点重合,则找到需要计算的线段 tree[rt].c+=e.f; calc(rt); return ; } if(e.y2<=tree[rt<<1].ry) update(rt<<1,e);若右端点在子节点的右边,即整个线段都在此端点右侧,就进子节点 else if(e.y1>=tree[rt<<1|1].ly) update(rt<<1|1,e);同上 else {线段被分成两份 line t=e; t.y2=tree[rt<<1].ry; update(rt<<1,t); t=e; t.y1=tree[rt<<1|1].ly; update(rt<<1|1,t); } calc(rt); } int main(){ int q=0; double ans=0; int t=1; double x1,x2,y1,y2; while(scanf("%d",&n)&&n){ ans=0; t=1; for (int i=1;i<=n;i++){ scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); l[t].x=x1; l[t].y1=y1; l[t].y2=y2; l[t].f=1; Y[t++]=y1; l[t].x=x2; l[t].y1=y1; l[t].y2=y2; l[t].f=-1; Y[t++]=y2; } sort(l+1,l+t,cmp); sort(Y+1,Y+t);排序来建树,找线段长度 build(1,1,t-1);只到t-1是因为t++ update(1,l[1]); for (int i=2;i<t;i++){ //printf("%lf ",tree[1].sum); ans+=(l[i].x-l[i-1].x)*tree[1].sum;端点一为线段总长度 update(1,l[i]); } printf("Test case #%d ", ++q); printf("Total explored area: %.2f ", ans); } return 0; }