原题链接:https://www.luogu.com.cn/problem/P5490

【模板】扫描线

题目描述

求 nnn 个矩形的面积并。

输入格式

第一行一个正整数 nnn。

接下来 nnn 行每行四个非负整数 x1,y1,x2,y2x_1, y_1, x_2, y_2x1​,y1​,x2​,y2​ ,表示一个矩形的左下角坐标为 (x1,y1)(x_1, y_1)(x1​,y1​),右上角坐标为 (x2,y2)(x_2, y_2)(x2​,y2​)。

输出格式

一行一个正整数,表示 nnn 个矩形的并集覆盖的总面积。

输入输出样例

输入 #1
2
100 100 200 200
150 150 250 255
输出 #1
18000

说明/提示

对于 20%20\%20% 的数据,1≤n≤10001 \le n \le 10001≤n≤1000。

对于 100%100\%100% 的数据,1≤n≤106,0≤x1<x2≤109,0≤y1<y2≤1091 \le n \le 10^6, 0 \le x_1 < x_2 \le 10^9, 0 \le y_1 < y_2 \le 10^91≤n≤106,0≤x1​<x2​≤109,0≤y1​<y2​≤109 。

题解

扫描线的模板题,然而原网页上的数据范围写的n≤105n\le 10^5n≤105,实际数据范围10610^6106就™离谱。

扫描线可以说是一种线段树的运用,也可以说是一种思想:在处理二维的问题时,可以先解决其中一维的问题,再沿着另一维拓展延伸。

对于求矩形面积并的问题,从多维视角上看,矩形面积实际上是一维的线段沿着另一维移动扫过的面积。这个问题转换到一维就是求出每个时刻原图形的截线长度,下图黄线所示就是若干时刻的截线:

更进一步,我们可以发现截线的长度仅在经过长方形的边时发生改变,所以有用的截线实际上只有这几条:

而截线长度的变化就是因为添加/删去了矩形的边,所以我们把矩形拆成上边和下边,从下往上遍历每个边,遇到下边时对覆盖的区间加一,遇到上边则对覆盖的区间减一;每完成一次更新,就乘以相邻边的高度差,如此就能得到矩形并的面积。

要完成区间加和整体求和的操作,只需要在离散化横坐标的基础上建立线段树维护区间被覆盖次数covcovcov和本区间内被覆盖的总长度lenlenlen。

代码

由于横坐标划分的区间是在实数域上的,所以在边界处理上与区间为整数域的线段树有所不同:

#include<bits/stdc++.h>
#define ls v<<1
#define rs v<<1|1
using namespace std;
const int M=1e6+5;
struct Edge{int le,ri,h,val;
}edge[M<<1];
bool cmp(Edge a,Edge b){return a.h<b.h;}
struct node{int le,ri,len,cov;
}tree[M<<2];
int n,tot,x[M],cot;
long long ans;
void up(int v){tree[v].len=tree[v].cov?tree[v].ri-tree[v].le:tree[ls].len+tree[rs].len;}
void build(int v,int le,int ri)
{tree[v].le=x[le],tree[v].ri=x[ri+1];if(le==ri)return;int mid=le+ri>>1;build(ls,le,mid),build(rs,mid+1,ri);
}
void cover(int v,int le,int ri,int val)
{if(le<=tree[v].le&&tree[v].ri<=ri){tree[v].cov+=val;up(v);return;}if(le<tree[ls].ri)cover(ls,le,ri,val);if(tree[rs].le<ri)cover(rs,le,ri,val);up(v);
}
void in()
{scanf("%d",&n);for(int i=1,a,b,c,d;i<=n;++i)scanf("%d%d%d%d",&a,&b,&c,&d),edge[++cot]=(Edge){a,c,b,1},edge[++cot]=(Edge){a,c,d,-1},x[++tot]=a,x[++tot]=c;
}
void ac()
{sort(x+1,x+1+tot);tot=unique(x+1,x+1+tot)-x-1;build(1,1,tot-1);sort(edge+1,edge+1+cot,cmp);for(int i=1;i<=cot;++i){ans+=1ll*tree[1].len*(edge[i].h-edge[i-1].h);cover(1,edge[i].le,edge[i].ri,edge[i].val);}printf("%lld\n",ans);
}
int main()
{in(),ac();//system("pause");
}

Luogu5490 【模板】扫描线(矩形的面积并)相关推荐

  1. HDU 1264 Counting Squares (线段树-扫描线-矩形面积并)

    版权声明:欢迎关注我的博客.本文为博主[炒饭君]原创文章,未经博主同意不得转载 https://blog.csdn.net/a1061747415/article/details/25471349 P ...

  2. 蓝桥杯 油漆面积【第八届】【省赛】【A组】线段树扫面线/求矩形相交面积/模拟

    资源限制 内存限制:256.0MB   C/C++时间限制:1.0s   Java时间限制:3.0s   Python时间限制:5.0s X星球的一批考古机器人正在一片废墟上考古. 该区域的地面坚硬如 ...

  3. Python使用matplotlib可视化Treemap图、treemap将分层数据显示为一组嵌套矩形,每一组都用一个矩形表示,该矩形的面积与其值成正比(Treemap)

    Python使用matplotlib可视化Treemap图.treemap将分层数据显示为一组嵌套矩形,每一组都用一个矩形表示,该矩形的面积与其值成正比(Treemap) 目录

  4. python中使用squarify包可视化treemap图:treemap将分层数据显示为一组嵌套矩形,每一组都用一个矩形表示,该矩形的面积与其值成正比

    python中使用squarify包可视化treemap图:treemap将分层数据显示为一组嵌套矩形,每一组都用一个矩形表示,该矩形的面积与其值成正比 目录

  5. python中使用squarify包可视化treemap图:treemap将分层数据显示为一组嵌套矩形,每一组都用一个矩形表示,该矩形的面积与其值成正比、自定义设置每一个数据格的颜色

    python中使用squarify包可视化treemap图:treemap将分层数据显示为一组嵌套矩形,每一组都用一个矩形表示,该矩形的面积与其值成正比.自定义设置每一个数据格的颜色 目录

  6. 使用类计算矩形的面积

    定义并实现一个矩形类,有长和宽两个属性,由成员函数计算矩形的面积. 矩形类Rectang接口定义如下: class Rectangle { public:void setLength(int l);/ ...

  7. 每天一道LeetCode-----计算直方图中最大矩形的面积

    Largest Rectangle in Histogram 原题链接Largest Rectangle in Histogram 给定一个直方图,计算这个直方图中最大的矩形面积.输入的是直方图中每个 ...

  8. python计算长方形面积代码_Python计算两个矩形重合面积代码实例

    这篇文章主要介绍了Python 实现两个矩形重合面积代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 代码如下 计算两个矩形的重合面积 imp ...

  9. C语言 有两个矩形 求重叠面积,计算两个矩形重叠面积的简单方法

    实验需要,需要计算两个矩形重叠面积 想来想去觉得挺复杂,搜了下,看见一个超给力的方法 这里分享下: function D = DecideOberlap(Reframe,GTframe) x1 = R ...

  10. 【C语言】输入矩形的长和宽,计算该矩形的面积

    C语言学习-输入矩形的长和宽,计算该矩形的面积 原理 面积(S)=  长(length)*  宽(width) 运行效果 代码 #include<stdio.h> main() {int ...

最新文章

  1. CALayer-层的属性
  2. zigbee的路由器能分配网络地址吗_网络基础知识学习 小白也能变专家
  3. 读”SQL Injection Pocket Reference”之摘录
  4. jQuery选择器的演示
  5. (多线程)leetcode1116. 打印零与奇偶数
  6. 从业6年,给你5点建议
  7. How to Install and Configure OpenSSH Server In Linux
  8. android 9.0华为荣耀,华为9款旗舰尝鲜Android 9.0 还不快去升
  9. 带有审图号的区位图制作
  10. Linux内核态下的文件操作
  11. nginx简介(轻量级开源高并发web服务器:大陆使用者百度、京东、新浪、网易、腾讯、淘宝等)(并发量5w)(一般网站apache够用了,而且稳定)...
  12. Android.mk调用bin/shell
  13. 总容易混淆的排序算法:直接选择、冒泡(鸡尾酒)、直接插入(二分插入)(希尔)...
  14. 各种LINUX资源链接
  15. 城市数据大脑:小汽车儿堵成翔?NONONO!
  16. 亚瑟阿伦的三十六个问题。
  17. uniapp的uni.compressImage压缩图片的巨坑
  18. 基于Azure Kinect SDK获取物体rgb图、深度图、红外IR图和点云数据并保存到本地
  19. 前端HTML调用jQuery库,属性操作:更换图片、添加字体样式(前端:HTML搭配jQuery系列教程六)
  20. Ubuntu 20.04 美化终端

热门文章

  1. Raki的读paper小记:A Unified MRC Framework for Named Entity Recognition
  2. SpringBoot 2.0 整合Mybatis详细步骤
  3. javascript事件委托和jQuery事件绑定on、off 和one以及on绑定多个事件(重要)
  4. Spring AOP之静态代理
  5. AWK相关学习(转)
  6. 安腾机器IA64 全自动网络安装Linux - elilo+kickstart
  7. MSSQL存储过程调用 C#DLL
  8. idea64.exe.vmoptions 参数意义
  9. redis info信息注解
  10. 垃圾回收相关算法总结