hdu 1542 扫描线求矩形面积的并
很久没做线段树了
讲的比较清楚的链接
求矩形面积的并
分析:
1.矩形比较多,坐标也很大,所以横坐标需要离散化(纵坐标不需要),熟悉离散化后这个步骤不难,所以这里不详细讲解了,不明白的还请百度
2.重点:扫描线法:假想有一条扫描线,从左往右(从右往左),或者从下往上(从上往下)扫描过整个多边形(或者说畸形。。多个矩形叠加后的那个图形)。如果是竖直方向上扫描,则是离散化横坐标,如果是水平方向上扫描,则是离散化纵坐标。
下面的分析都是离散化横坐标的,并且从下往上扫描的。
扫描之前还需要做一个工作,就是保存好所有矩形的上下边,并且按照它们所处的高度进行排序,另外如果是上边我们给他一个值-1,下边给他一个值1,我们用一个结构体来保存所有的上下边
struct segment
{
double l,r,h; //l,r表示这条上下边的左右坐标,h是这条边所处的高度
int f; //所赋的值,1或-1
}
接着扫描线从下往上扫描,每遇到一条上下边就停下来,将这条线段投影到总区间上(总区间就是整个多边形横跨的长度),这个投影对应的其实是个插入和删除线段操作。还记得给他们赋的值1或-1吗,下边是1,扫描到下边的话相当于往总区间插入一条线段,
上边-1,扫描到上边相当于在总区间删除一条线段(如果说插入删除比较抽象,
那么就直白说,扫描到下边,投影到总区间,对应的那一段的值都要增1,扫描到上边对应的那一段的值都要减1,如果总区间某一段的值为0,说明其实没有线段覆盖到它,为正数则有,那会不会为负数呢?是不可能的,可以自己思考一下)。
每扫描到一条上下边后并投影到总区间后,就判断总区间现在被覆盖的总长度,然后用下一条边的高度减去当前这条边的高度,乘上总区间被覆盖的长度,就能得到一块面积,并依此做下去,就能得到最后的面积
Sample Input
2
10 10 20 20
15 15 25 25.5
0
Sample Output
Test case #1
Total explored area: 180.00
- #include <cstdio>
- #include <cstring>
- #include <cctype>
- #include <algorithm>
- using namespace std;
- #define lson l , m , rt << 1
- #define rson m + 1 , r , rt << 1 | 1
- const int maxn = ;
- int cnt[maxn << ];
- double sum[maxn << ];
- double X[maxn];
- struct Seg {
- double h , l , r;
- int s;
- Seg(){}
- Seg(double a,double b,double c,int d) : l(a) , r(b) , h(c) , s(d) {}
- bool operator < (const Seg &cmp) const {
- return h < cmp.h;
- }
- }ss[maxn];
- void PushUp(int rt,int l,int r) {
- if (cnt[rt]) sum[rt] = X[r+] - X[l];
- else if (l == r) sum[rt] = ;
- else sum[rt] = sum[rt<<] + sum[rt<<|];
- }
- void update(int L,int R,int c,int l,int r,int rt) {
- if (L <= l && r <= R) {
- cnt[rt] += c;
- PushUp(rt , l , r);
- return ;
- }
- int m = (l + r) >> ;
- if (L <= m) update(L , R , c , lson);
- if (m < R) update(L , R , c , rson);
- PushUp(rt , l , r);
- }
- int Bin(double key,int n,double X[]) {
- int l = , r = n - ;
- while (l <= r) {
- int m = (l + r) >> ;
- if (X[m] == key) return m;
- if (X[m] < key) l = m + ;
- else r = m - ;
- }
- return -;
- }
- int main() {
- int n , cas = ;
- while (~scanf("%d",&n) && n) {
- int m = ;
- while (n --) {
- double a , b , c , d;
- scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
- X[m] = a;
- ss[m++] = Seg(a , c , b , );
- X[m] = c;
- ss[m++] = Seg(a , c , d , -);
- }
- sort(X , X + m);
- sort(ss , ss + m);
- int k = ;
- for (int i = ; i < m ; i ++) {
- if (X[i] != X[i-]) X[k++] = X[i];
- }
- memset(cnt , , sizeof(cnt));
- memset(sum , , sizeof(sum));
- double ret = ;
- for (int i = ; i < m - ; i ++) {
- int l = Bin(ss[i].l , k , X);
- int r = Bin(ss[i].r , k , X) - ;
- if (l <= r) update(l , r , ss[i].s , , k - , );
- ret += sum[] * (ss[i+].h - ss[i].h);
- }
- printf("Test case #%d\nTotal explored area: %.2lf\n\n",cas++ , ret);
- }
- return ;
- }
hdu 1542 扫描线求矩形面积的并的更多相关文章
- HDU 1542"Atlantis"(线段树+扫描线求矩形面积并)
传送门 •题意 给你 n 矩形,每个矩形给出你 $(x_1,y_1),(x_2,y_2)$ 分别表示这个矩形的左下角和右上角坐标: 让你求这 n 个矩形并的面积: 其中 $x \leq 10^{5} ...
- hdu 1542&&poj 1151 Atlantis[线段树+扫描线求矩形面积的并]
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- HDU 1542 Atlantis(矩形面积并)
HDU 1542 Atlantis 题目链接 题意:给定一些矩形,求面积并 思路:利用扫描线,因为这题矩形个数不多,直接暴力扫就能够了.假设数据大.就要用线段树 代码: #include <cs ...
- HDU 3265 扫描线(矩形面积并变形)
Posters Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- 【HDU 1542】Atlantis 矩形面积并(线段树,扫描法)
[题目] Atlantis Problem Description There are several ancient Greek texts that contain descriptions of ...
- 2015 UESTC 数据结构专题E题 秋实大哥与家 线段树扫描线求矩形面积交
E - 秋实大哥与家 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/59 De ...
- hdu1828 线段树扫描线求矩形面积的周长
题意: 给你n个矩形,问你这n个矩形所围成的图形的周长是多少. 思路: 线段树的扫描线简单应用,这个题目我用的方法比较笨,就是扫描两次,上下扫描,求出多边形的上下边长和,然后同 ...
- hdu1542 线段树扫描线求矩形面积的并
题意: 给你n个正方形,求出他们的所占面积有多大,重叠的部分只能算一次. 思路: 自己的第一道线段树扫描线题目,至于扫描线,最近会写一个总结,现在就不直接在这里写了,说下我的方 ...
- HDU 1542.Atlantis-线段树求矩形面积并(离散化、扫描线/线段树)-贴模板
好久没写过博客了,这学期不是很有热情去写博客,写过的题也懒得写题解.现在来水一水博客,写一下若干年前的题目的题解. Atlantis Time Limit: 2000/1000 MS (Java/Ot ...
随机推荐
- 学习Linux下的IP地址地理位置信息显示工具nali
首先详细教程已经有前辈做了详细的安装和使用介绍,本人只是参照学习和记录下自己的实际操做. 本文参考档:http://www.cnblogs.com/mchina/archive/2012/12/24/ ...
- 超常用的PHP正则表达式收集整理
以下就是对超常用的PHP正则表达式进行的收集整理,为了方便大家更快更好的掌握php正则表达式. 一.表单验证匹配验证账号,字母开头,允许 5-16 字节,允许字母数字下划线:^[a-zA-Z][a-z ...
- 用纯原生js实现jquery的ready函数(两种实现)
第一种实现方式: var dom = new function() { var dom = []; dom.isReady = false; dom.isFunction = function(obj ...
- 读>>>>白帽子讲Web安全<<<<摘要→我推荐的一本书→1
<白帽子讲Web安全>吴翰清著 刚开始看这本书就被这本书吸引,感觉挺不错,给大家推荐下,最近读这本书,感觉不错的精华就记录下, 俗话说>>>好脑袋不如一个烂笔头< ...
- 繁华模拟赛 Evensgn的债务
#include<iostream> #include<cstdio> #include<string> #include<cstring> #incl ...
- C语言课程1——Hello World
相信大家看了第一篇文章后,都信心满满,后边咱来点实际吧,上代码,经典之作:Hello World. 首先,不知道大家用的什么工具,VC6.0(太老了,强烈建议不用),VS,或是其他~ Hello Wo ...
- 使用HTML5 Web存储的localStorage和sessionStorage方式
localStorage(本地存储),可以长期存储数据,没有时间限制,一天,一年,两年甚至更长,数据都可以使用.sessionStorage(会话存储),只有在浏览器被关闭之前使用,创建另一个页面时同 ...
- Centos 7 安装LAMP环境
一.安装Centos 官网下载Centos 7刻录成光盘后安装 二.安装apache yum install httpd #根据提示,输入Y安装即可成功安装 systemctl start httpd ...
- Linux_DHCP服务搭建
Linux网络参数的设置 1. 修改主机名 # vim /etc/sysconfig/network NETWORKING=yes HOSTNAME=bj.com 2. 修 ...
- Java RMI 框架
RMI(即Remote Method Invoke 远程方法调用).在Java中,只要一个类extends了java.rmi.Remote接口,即可成为存在于服务器端的远程对象,供客户端访问并提供一定 ...