<题目链接>

题目大意:

给你n个矩形,求出它们面积的并。

解题分析:

此题主要用到了扫描线的思想,现将各个矩形的横坐标离散化,然后用它们离散化后的横坐标(相当于将矩形的每条竖线投影在x轴上,然后将它们从0~n-1标号),并且利用这些标好的号建线段树,线段树的每个叶子节点表示离散化后的横坐标(比如从左往右数第一个叶子节点,它的区域表示的就是第0个竖线)。建好数后,就用扫描线从下至上进行扫描,若为下边界,则add[rt]+=1,若为上边界,则add[rt]-=1;扫描线到上面一个边界时,就用高度差*整个区域内的有效长度,即为这一部分矩形的面积。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5.  
  6. #define Lson rt<<1,l,mid
  7. #define Rson rt<<1|1,mid+1,r //线段树的每一个节点都有对应的add和sum值
  8. const int M =;
  9. int add[M<<]; //add为区间标记,标记这段区间是否有效(是不是对求面积做出贡献的一段)
  10. double sum[M<<],x[M<<]; //sum表示这段区间内总共的有效长度
  11.  
  12. struct node{
  13. int cnt; //cnt=1为下边,cnt=-1为上边
  14. double l,r,h; //分别记录线段的左端,右端和高度
  15. node(){}
  16. node(double a,double b,double c,int d):l(a),r(b),h(c),cnt(d){}
  17. friend bool operator <(node tmp1,node tmp2){
  18. return tmp1.h<tmp2.h; //从下往上扫,所以将h从小到大排序
  19. }
  20. }s[M<<];
  21. void Pushup(int rt,int l,int r){
  22. if(add[rt])sum[rt]=x[r+]-x[l]; //如果这段区域add不为0,则说明这段区域全部有效,由于原来查询的时候是左闭右开,所以这里的真实区域要+1
  23. else if(l==r)sum[rt]=;
  24. else sum[rt]=sum[rt<<]+sum[rt<<|]; //求出这段区域的真正有效长度
  25. }
  26. void update(int rt,int l,int r,int L,int R,int cor){
  27. if(L<=l&&r<=R){
  28. add[rt]+=cor;
  29. Pushup(rt,l,r); //由于add标记改变了,所以更新一下tr[rt]的sum值
  30. return;
  31. }
  32. int mid=(l+r)>>;
  33. if(L<=mid)update(Lson,L,R,cor);
  34. if(R>mid)update(Rson,L,R,cor);
  35. Pushup(rt,l,r); //用递归更新一下路径上的所有sum值
  36. }
  37.  
  38. int main(){
  39. int n,ncase=;
  40. while(scanf("%d",&n)!=EOF,n){
  41. double a,b,c,d;
  42. int m=;
  43. for(int i=;i<n;i++){
  44. scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
  45. x[m]=a;
  46. s[m++]=node(a,c,b,); //矩形下面那条边
  47. x[m]=c;
  48. s[m++]=node(a,c,d,-);
  49. }
  50. sort(x,x+m);
  51. sort(s,s+m);
  52. memset(add,,sizeof(add)); //这两个memset相当于建树
  53. memset(sum,,sizeof(sum));
  54. int k=;
  55. for(int i=;i<m;i++){
  56. if(x[i]!=x[i-]){
  57. x[k++]=x[i]; //去重
  58. }
  59. }
  60. //0~k-1为离散化后的线段树sum[1]所对应的区域
  61. double ans=;
  62. for(int i=;i<m-;i++){ //这里只需要循环m-1次就行,因为一共有m-1段面积
  63. int l=lower_bound(x,x+k,s[i].l)-x;
  64. int r=lower_bound(x,x+k,s[i].r)-x-; //为避免边的边界重复,我们选取左闭右开区间,所以r要减1
  65. update(,,k-,l,r,s[i].cnt);
  66. ans+=sum[]*(s[i+].h-s[i].h); //sum[1]代表 X(min)~X(max)区域内的有效线段长度,即需要乘以高度差的线段长度
  67. }
  68. printf("Test case #%d\n", ++ncase);
  69. printf("Total explored area: %.2lf\n\n", ans);
  70. }
  71. return ;
  72. }

2018-07-25

HDU 1542 矩形面积并【离散化+线段树+扫描线】的更多相关文章

  1. POJ 1151 Atlantis 矩形面积求交/线段树扫描线

    Atlantis 题目连接 http://poj.org/problem?id=1151 Description here are several ancient Greek texts that c ...

  2. 51nod 1206 Picture 矩形周长求并 | 线段树 扫描线

    51nod 1206 Picture 矩形周长求并 | 线段树 扫描线 #include <cstdio> #include <cmath> #include <cstr ...

  3. HDU 4419 Colourful Rectangle --离散化+线段树扫描线

    题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何 ...

  4. 【HDU 1542】Atlantis 矩形面积并(线段树,扫描法)

    [题目] Atlantis Problem Description There are several ancient Greek texts that contain descriptions of ...

  5. hdu1542 矩形面积并(线段树+离散化+扫描线)

    题意: 给你n个矩形,输入每个矩形的左上角坐标和右下角坐标. 然后求矩形的总面积.(矩形可能相交). 题解: 前言: 先说说做这道题的感受: 刚看到这道题顿时就懵逼了,几何 烂的渣渣.后来从网上搜题解 ...

  6. ZOJ 2301 / HDU 1199 Color the Ball 离散化+线段树区间连续最大和

    题意:给你n个球排成一行,初始都为黑色,现在给一些操作(L,R,color),给[L,R]区间内的求染上颜色color,'w'为白,'b'为黑.问最后最长的白色区间的起点和终点的位置. 解法:先离散化 ...

  7. hdu 1199 Color the Ball(离散化线段树)

    Color the Ball Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) T ...

  8. POJ1177 Picture —— 求矩形并的周长 线段树 + 扫描线 + 离散化

    题目链接:https://vjudge.net/problem/POJ-1177 A number of rectangular posters, photographs and other pict ...

  9. HDU 1542 矩形面积并

    推荐阅读这篇文章 这里仅根据上述文章进行一些补充.主要是注意这里线段树点的意义变成了“边”.比如+-----+-----+,看作3个点abc和两条边e1和e2,那么线段树中点a代表e1,点b代表e2. ...

随机推荐

  1. UE4的AI学习(1)——基本概念

    AI学习当中,不学习行为树基本概念就不能明白具体实例中的操作意义,但是没有经过具体实例实验,又觉得基本概念抽象难以理解.建议先泛读(1)(2)后再对具体的细节进行死磕,能较深的理解行为树的具体概念.第 ...

  2. A - The Water Bowls POJ - 3185 (bfs||高斯消元)

    题目链接:https://vjudge.net/contest/276374#problem/A 题目大意:给你20个杯子,每一次操作,假设当前是对第i个位置进行操作,那么第i个位置,第i+1个位置, ...

  3. KEYCODE_DPAD_CENTER 和 KEYCODE_ENTER

    KEYCODE_DPAD_CENTER或者是KEYCODE_ENTER时,会在view优先处理isConfirmKey,而在activity中的onKeyDown和up中接收不到该按键消息

  4. Tensorflow datasets.shuffle repeat batch方法

    机器学习中数据读取是很重要的一个环节,TensorFlow也提供了很多实用的方法,为了避免以后时间久了又忘记,所以写下笔记以备日后查看. 最普通的正常情况 首先我们看看最普通的情况: # 创建0-10 ...

  5. 2017-2018-2 20155303『网络对抗技术』Final:Web渗透获取WebShell权限

    2017-2018-2 『网络对抗技术』Final:Web渗透获取WebShell权限 --------CONTENTS-------- 一.Webshell原理 1.什么是WebShell 2.We ...

  6. SpringAOP+注解实现简单的日志管理

    今天在再次深入学习SpringAOP之后想着基于注解的AOP实现日志功能,在面试过程中我们也经常会被问到:假如项目已经上线,如何增加一套日志功能?我们会说使用AOP,AOP也符合开闭原则:对代码的修改 ...

  7. 解决kali linux 开启ssh服务后连接不上的问题

    今天在手机端装了NetHunter 想连接PC的kali ,可是怎么都连不上 综合网友的经验: 1.修改sshd_config文件,命令为:vi /etc/ssh/sshd_config 将#Pass ...

  8. python正则表达式一[转]

    原文:http://blog.jobbole.com/74844/ 作为一个概念而言,正则表达式对于Python来说并不是独有的.但是,Python中的正则表达式在实际使用过程中还是有一些细小的差别. ...

  9. Generative Adversarial Nets(原生GAN学习)

    学习总结于国立台湾大学 :李宏毅老师 Author: Ian Goodfellow • Paper: https://arxiv.org/abs/1701.00160 • Video: https:/ ...

  10. linux下ssh远程连接工具SecureCRT和xshell编码设置

    默认的编码有时候显示乱码,需要切换到utf-8 xshell的设置 多个会话窗口执行同样命令 中文界面: