Codevs 题目3044 矩形面积求并(线段树+扫描线+离散化)
2015-09-02 18:45
435 查看
3044 矩形面积求并
时间限制: 1 s空间限制: 256000 KB
题目等级 : 钻石 Diamond
题解
查看运行结果
题目描述 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
2 10 10 20 20 15 15 25 25.5 0
样例输出 Sample Output
180.00
数据范围及提示 Data Size & Hint
无
分类标签 Tags 点此展开
原来这就是扫描线啊,把线段按y从小到大排序,然后从下到上的扫,用一个flag记录+1表示矩形的底边,-1表示矩形的顶边,用个col记录,每次加上flag,从上往下扫的时候,记录当前的线段在x轴上的投影,就是长的贡献,即sum[1],然后乘以这个线段和他上边第一个线段的y的差值,就是高的贡献,要是扫过这个矩形的的底和顶对x的轴的投影贡献就不算他了,col就消去了,col>0时说明这段区间一定对x轴有投影,n条线段扫n-1次就可以了。ac代码
评测ID: 1507846 用户名: 略懂_is_a_Joker 状态: 测试通过 Accepted 得分 : 100 总时间耗费: 8ms 总内存耗费: 256 kB
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<algorithm> using namespace std; struct s { double x1,x2,y; int flag; }a[880]; double hash[805],sum[805]; int col[805]; int cmp(s a,s b) { return a.y<b.y; } int bseach(double key,int n) { int l=1,r=n; while(l<=r) { int mid=(l+r)>>1; if(hash[mid]==key) return mid; if(hash[mid]<key) l=mid+1; else r=mid-1; } return l; } void pushup(int tr,int l,int r) { if(col) sum =hash[r+1]-hash[l]; else if(l==r) sum =0; else sum =sum[tr<<1]+sum[tr<<1|1]; } void update(int L,int R,int l,int r,int tr,int flag) { if(L<=l&&r<=R) { col +=flag; pushup(tr,l,r); return; } int mid=(l+r)>>1; if(L<=mid) update(L,R,l,mid,tr<<1,flag); if(R>mid) update(L,R,mid+1,r,tr<<1|1,flag); pushup(tr,l,r); } int main() { int n; while(scanf("%d",&n)!=EOF) { if(n==0) break; memset(col,0,sizeof(col)); memset(sum,0,sizeof(sum)); double x1,x2,y1,y2; int i,k=1; for(i=1;i<=n;i++) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); a[k].x1=x1; a[k].x2=x2; a[k].y=y1; a[k].flag=1; hash[k++]=x1; a[k].x1=x1; a[k].x2=x2; a[k].y=y2; a[k].flag=-1; hash[k++]=x2; } sort(a+1,a+k,cmp); //int cnt=unique(hash+1,hash+k)-(hash+1); sort(hash+1,hash+k); double ans=0; for(i=1;i<k-1;i++) { int x,y; x=bseach(a[i].x1,k-1); y=bseach(a[i].x2,k-1)-1; if(x<=y) update(x,y,1,k-1,1,a[i].flag); ans+=sum[1]*(a[i+1].y-a[i].y); } printf("%.2lf\n",ans); } } 相关文章推荐
- C++项目开发常用的开源库
- Swift 设置文字阴影
- Angular实现递归指令 - Tree View
- java使用Junit工具进行单元测试
- 深入浅出CChart 每日一课——快乐高四第十五课 罗马通途,利用ChartCtrl控件实现多区域绘图
- 前端入门之css浮动
- linux下ssh安全连接
- BigInteger和BigDecimal的实例
- MySQL用户远程登录以及root密码设置
- 我的游戏开发笔记(六):NavMeshAgent及自动寻径(跳跃)。
- 我的渺小
- js学习
- OC 中#pragma mark [-] xxx
- HTML5离线存储
- OPS - Parrallel Control System
- Node.js最新Web技术栈(2015年5月)
- HDU 4634 Swipe Bo (BFS)
- FZU 2195 检查站点 (树形dp)
- [JavaScript 随笔] 垃圾回收
- 【LeetCode】之Remove Duplicates from Sorted Array