wikioi 3044 矩形面积求并

来源:互联网 发布:win10网络重置在哪里 编辑:程序博客网 时间:2024/05/02 04:37

输入n个矩形,求他们总共占地面积(也就是求一下面积的并)

可能有多组数据,读到n=0为止(不超过15组)

每组数据第一行一个数n,表示矩形个数(n<=100)

接下来n行每行4个实数x1,y1,x2,y1(0 <= x1 < x2 <= 100000;0 <= y1 < y2 <= 100000),表示矩形的左下角坐标和右上角坐标

每组数据输出一行表示答案

210 10 20 2015 15 25 25.50
180.00

题解

扫描线+离散+线段树的经典例题。扫描线详解请见http://hzwer.com/879.html

此题因为横坐标包含浮点数,因此先离散化。我用的是平行x轴的从下到上的扫描线,所以离散的是离散x坐标。

另外,因为用线段树维护的是覆盖在x轴上的边,我开始有想过离散过后将重复的点只保留一个,可是写线段树的时候发现这样无法计算总和。看了hzwer的题解后才明白:边是连续的,并非是一个个断点,因此线段树的每一个结点实际存储的是该节点左端点到右端点+1的距离。

#include<cstdio>#include<iostream>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#define inf 1<<30using namespace std;int n;struct xian {double x1,x2,y;int v;} a[205];double hash[205],ans;struct shu {int l,r,c; double sum;} tr[8000];//*********************************************************************bool kp(const xian &i,const xian &j) {return i.y<j.y;}void build(int w,int b,int e){tr[w].l=b; tr[w].r=e; tr[w].c=0;tr[w].sum=0;if(b==e) return;int mid=(b+e)>>1;build(w<<1,b,mid); build((w<<1)+1,mid+1,e);}void init(){int i,w,t;double x1,x2,y1,y2;for(i=1;i<=n;i++)   {w=(i<<1)-1; t=i<<1;scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);    a[w].x1=x1; a[w].x2=x2; a[w].y=y1; a[w].v=1;    a[t].x1=x1; a[t].x2=x2; a[t].y=y2; a[t].v=-1;    hash[w]=x1; hash[t]=x2;   }sort(hash+1,hash+n+n+1);sort(a+1,a+n+n+1,kp);/*hash[0]=-inf;for(i=1;i<=n+n;i++)   {if(hash[i]!=hash[i-1]) s[++size]=hash[i];}*/}int find(double x){int l=1,r=n<<1,mid;while(l<=r)   {mid=(l+r)>>1;    if(hash[mid]==x) return mid;    else if(hash[mid]>x) r=mid-1;    else l=mid+1;   }}void up(int w){if(tr[w].c) tr[w].sum=hash[tr[w].r+1]-hash[tr[w].l];else if(tr[w].l==tr[w].r) tr[w].sum=0;else tr[w].sum=tr[w<<1].sum+tr[(w<<1)+1].sum;}void insert(int w,int b,int e,int v){int l=tr[w].l,r=tr[w].r,mid;if(l==b&&r==e)   {tr[w].c+=v; up(w); return ;}mid=(l+r)>>1;if(e<=mid) insert(w<<1,b,e,v);else if(b>mid) insert((w<<1)+1,b,e,v);else   {insert(w<<1,b,mid,v);    insert((w<<1)+1,mid+1,e,v);   }up(w);}void work(){int i,l,r;ans=0;for(i=1;i<=n+n;i++)   {l=find(a[i].x1); r=find(a[i].x2)-1;    if(l<=r) insert(1,l,r,a[i].v);ans+=tr[1].sum*(a[i+1].y-a[i].y);   }printf("%.2lf\n",ans);}int main(){while(scanf("%d",&n)&&n)   {init();    build(1,1,n+n);    work();   }return 0;}


0 0
原创粉丝点击