wikioi 3044 矩形面积求并
来源:互联网 发布:win10网络重置在哪里 编辑:程序博客网 时间:2024/05/02 04:37
题目描述 Description
输入n个矩形,求他们总共占地面积(也就是求一下面积的并)
输入描述 Input Description
可能有多组数据,读到n=0为止(不超过15组)
每组数据第一行一个数n,表示矩形个数(n<=100)
接下来n行每行4个实数x1,y1,x2,y1(0 <= x1 < x2 <= 100000;0 <= y1 < y2 <= 100000),表示矩形的左下角坐标和右上角坐标
输出描述 Output Description
每组数据输出一行表示答案
样例输入 Sample Input
210 10 20 2015 15 25 25.50
样例输出 Sample Output
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
- wikioi 3044 矩形面积求并
- wikioi p3044 矩形面积求并
- 3044矩形面积求并
- 矩形面积求并
- [CODEVS 3044] 矩形面积求并
- 矩形切割-面积求并
- CodeVS3044矩形面积求并
- codevs3044 矩形面积求并
- 求矩形并的面积
- 【codevs3044】矩形面积求并
- 求矩形并的面积
- codevs 3044_矩形面积求并_离散
- [Codevs] 3044 矩形面积求并(离散化)
- 线段树 求矩形并 面积
- hdu3265(线段树求矩形面积并)
- hdu 1542 求矩形并的面积
- 离散化矩形面积求并
- HDU1542 线扫描求矩形面积并
- netty 源码分析二
- 【IOS】保存用户唯一ID
- a.html 与 a.js ,juery 简单练习
- Androidapi.JNI.Net.Wifi
- win7安装mysql5.6
- wikioi 3044 矩形面积求并
- Spring.Net 面向切面AOP
- 符合v大是否
- SPOJ 839 Optimal Marks 最小割 经典 按位建图
- 13.12 Word Break
- 利用javascript判断浏览器是否已经安装ActiveX控件和是否禁止运行ActiveX控件
- C++ vector用法
- Mybatis笔记之三 -- 映射关系(一对多)
- 方法的开发魔法