【恐怖の算法】 扫描线

news/2024/12/5 9:55:58/文章来源:https://www.cnblogs.com/yhy2013/p/18585168

【恐怖の算法】 扫描线

引入

扫描线一般运用在图形上面,它和它的字面意思十分相似,就是一条线在整个图上扫来扫去,它一般被用来解决图形面积,周长,以及二维数点等问题。

二维矩形面积并问题

在二维坐标系上,给出多个矩形的左下以及右上坐标,求出所有矩形构成的图形的面积。

过程

根据图片可知总面积可以直接暴力即可求出面积,如果数据大了怎么办?这时就需要讲到 扫描线 算法。

现在假设我们有一根线,从下往上开始扫描:

扫描线示意图

按这样把矩形分成几个部分,小矩形的高是扫过的距离。我们可以发现,小矩形的宽一直在变化。

给每一个矩形的上下边进行标记,下面的边标记为 1,上面的边标记为 -1。每遇到一个水平边时,让这条边(在横轴投影区间)的权值加上这条边的标记。

小矩形(不一定只有一个)的宽度就是整个数轴上权值大于 0 的区间总长度。

实现

很容易想到可以用线段树。

用线段树维护矩形的长,也就是整个数轴上覆盖次数大于 0 的点。

需求列举如下:

  • 一段区间权值加 1、减 1。

  • 统计整个数轴上,区间权值大于 0 的「区间长度和」。

如果你尝试直接用普通线段树模板来实现的话,也许会遇到些挫折。具体地,由于在区间加时,即使修改区间和节点管理区间重合,我们还是不能常数时间知道覆盖次数如何变化。这是因为我们不能直接知道:管理范围里有多长的区间会从 1 变成 0(从 0 变成 1)。

这道题只需要朴素的分治就能实现:维护每个节点管理区间中「整体 修改的权值和 w[]」(类似不用下放的懒惰标记)和「覆盖长度 v[]」两个信息。

需要用到离散化。

例题

题目传送门:CZOJ #25.「模板」扫描线

分析

模版题,同理直接用线段树

离散化+线段树+模拟

由于数据量太大,我们先把所有的墙壁离散化,用线段树维护每个离散化后的横坐标的最高点,然后模拟求出答案。

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int n;
struct a {int x;int h;int v;int l;
} r[200005] = {};
int d[100005] = {};
int cmh(a x, a y) { return x.h < y.h; }
int cmx(a x, a y) { return x.x < y.x; }
int t[400005] = {};
int m = 0, ans[400005][2] = {};
void ad(int k, int x, int l, int r, int v) {int mid = (l + r) / 2;t[k] += v;if (l != r) {if (x <= mid) {ad(k * 2, x, l, mid, v);} else {ad(k * 2 + 1, x, mid + 1, r, v);}}
}
int rank(int k, int l, int r) {int mid = (l + r) / 2;if (t[k] == 0) {return 0;}if (l == r) {return mid;}if (t[k * 2 + 1] == 0) {rank(k * 2, l, mid);} else {rank(k * 2 + 1, mid + 1, r);}
}
int main() {cin >> n;for (int i = 1; i <= n; i++) {cin >> r[i * 2].h >> r[i * 2 - 1].x >> r[i * 2].x;r[i * 2 - 1].h = r[i * 2].h;r[i * 2 - 1].v = 1;r[i * 2].v = -1;}sort(r + 1, r + 2 * n + 1, cmh);r[0].x = 1000000001;r[2 * n + 1].x = r[0].x;for (int i = 1; i <= 2 * n; i++) {r[i].l = r[i - 1].l + (r[i].h != r[i - 1].h);d[r[i].l] = r[i].h;}sort(r + 1, r + 2 * n + 1, cmx);int i = 1, j = 1;int now = 0, pas = 0;while (i <= 2 * n) {j = i;while (r[j].x == r[i].x) {ad(1, r[i].l, 1, 100000, r[i].v);now = rank(1, 1, 100000);i++;}if (pas != now) {m++;ans[m][0] = r[j].x;ans[m][1] = d[pas];m++;ans[m][0] = r[j].x;ans[m][1] = d[now];pas = now;}}ans[m][1] = 0;cout << m << endl;for (int i = 1; i <= m; i++) {cout << ans[i][0] << " " << ans[i][1] << endl;}
}

噩梦算法の终结~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/846353.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

堆栈2

1、 2、push 3push 2push 1 只有ESP发生变化(ESP=ESP-c),1、2、3也被压入栈 3、CALL 00401005(按F7不按F8) 把这个值(它的下一行)压入堆栈,EIP修改00401005(与9相同)按F7之后会生成一个JMP指令4、PUSH EBPMOV EBP,ESPSUB ESP,48 5、PUSH EBXPUSH ESIPUSH EDI 6、…

vxe-table 在 vxe-tabs 页签组件中使用表格

在 vxe-tabs 页签组件中使用 vxe-table 表格组件,自适应页签高度。 官网:https://vxetable.cn/<template><div><vxe-tabs padding><vxe-tab-pane title="页签1" name="1"><vxe-grid v-bind="gridOptions1"><…

jar包目录介绍

jar包目录介绍BOOT-INF:包含class文件和依赖jar META-INF:包含Class-Path:指定执行运行jar时的classpath; Main-Class:指定运行时的main方法所在类 org:包含springboot一些文件重要信息官网:https://ais.cn/u/vEbMBz

傻瓜式jvm基础学习

Q:jvm调优是在做什么? A:通过修改jvm参数和更换合适的垃圾回收器从而达到提高垃圾回收效率、降低停顿时间,提高系统的吞吐量和响应速度。从上面的问答中可以得到两个概念,jvm参数、垃圾回收器。程序计数器存储当前线程正在执行的Java方法的字节码指令地址的内存区域,作为…

既然overleaf崩了,那就立马尝试装本地的latex吧

目前还没定下来具体的latex搭配方案,只是先安装了各个软件 参考博客:https://zhuanlan.zhihu.com/p/607473890VSCode+Texlive+LaTeX Workshop+Copilot AI辅助写作 (推荐)参考博客:https://blog.csdn.net/Luan__Yu/article/details/143562703 超详细2024版Latex安装Texlive…

Everything 重大更新(新增拼音搜索 + 文档内容搜索)

Everything 重大更新(新增拼音搜索 + 文档内容搜索)原文:https://mp.weixin.qq.com/s/rrrijG0HXbQaCssWN9zAkQ Everything v1.5a 新版本开启拼音搜索的方法 现在官方更新,终于直接内置了中文拼音缩写搜索功能了! 另外,新版 Everything 还加入了呼声很高的文件全文内容搜索功…

jfinal 快速入门

0000package cn.jbolt.starter;import cn.jbolt.config.AppConfig; // 导入应用配置类 import com.jfinal.server.undertow.UndertowServer; // 导入Undertow服务器类// 主应用类 public class App {// 主函数,程序的入口点public static void main(String[] args) {// 创建Un…

高精度计算器-Qt版

代码 widget.h 文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <vector> #include <stack> using namespace std;QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:…

Power Automate 获取用户属性

前言最近,要在项目里需要获取用户的属性正文在Power Automate里有个Office 365 Users,里面有Action可以获取用户属性执行的结果,可以获取到很多属性,当然,这里都是默认的,如果想要更多的属性,在Select fields里添加就可以了。结束语想要其它的属性,参考官网就可以了。u…

JavaSwing 事件处理

1. 事件类型 2. ActionListenera:如果同一个组件添加了多个监听器,则每个监听器都会被执行, 后添加监听器会先被执行!b: 同一个监听器对象,可以监听多个组件!try{BeautyEyeLNFHelper.frameBorderStyle = BeautyEyeLNFHelper.FrameBorderStyle.osLookAndFeelDecorated;o…

C#/.NET/.NET Core技术前沿周刊 | 第 15 期(2024年11.25-11.30)

前言 C#/.NET/.NET Core技术前沿周刊,你的每周技术指南针!记录、追踪C#/.NET/.NET Core领域、生态的每周最新、最实用、最有价值的技术文章、社区动态、优质项目和学习资源等。让你时刻站在技术前沿,助力技术成长与视野拓宽。欢迎投稿、推荐或自荐优质文章、项目、学习资源等…

学期2024-2025-1 学号20241424 《计算机基础与程序设计》第11周学习总结

学期2024-2025-1 学号20241424 《计算机基础与程序设计》第11周学习总结 作业信息这个作业属于哪个课程 2024-2025-1-计算机基础与程序设计)这个作业要求在哪里 2024-2025-1计算机基础与程序设计第十一周作业这个作业的目标 <1.学习计算机科学概论第15,16章 并完成云班课测…