【2024最新】C++扫描线算法介绍+实战例题
扫描线介绍:OI-Wiki
【简单】一维扫描线(差分优化)
网上一维扫描线很少有人讲,可能认为它太简单了吧,也可能认为这应该算在差分里(事实上讲差分的文章里也几乎没有扫描线的影子)。但我认为,一维扫描线是十分重要、也是十分套路的,学过和没学过的差距很明显。希望大家认真学习。
例1
有n个点,m组[ai,bi),求所有m个区间重叠的部分有多少个位置。其中m<=1e6,0<=ai<bi<=n<=1e9
可以用扫描线思想。
扫描线可以看作是差分的优化,差分处理对a[s]~a[t]中的元素+1的方法:d[s]+=1, d[t+1]-=1
但差分求值需要遍历整个d数组,时间、空间复杂度为O(n),n为被修改数组的长度
如果长度太长(比如1e9),就会空间过大+超时
这时就可以上扫描线,其核心思想就是把差分在数组上的操作抽象成对数轴上若干个点的操作
例如:差分方法:d[s]+=1,d[t+1]-=1; 扫描线方法:在数组尾部插入 {s,+1} {t+1,-1}
这样只要对存储点修改的数组进行遍历,再用累加变量累加修改值,就能实时得到当前点的值
同时,当前修改点和上一个修改点之间的所有数组元素,其值都是上一个修改点位置的累加变量
这样时间、空间复杂度都为O(m),m为修改点的个数,肯定能过
扫描线的注意事项:
1.存储点修改的数组,用vector方便,但有常数过大而超时的风险。建议在m比较大的时候使用普通数组
2.存储所有修改点之后一定要按照修改位置从小到大排序,不然就乱了
3.排序后还要处理同一个点多次修改的重复问题,有三种主流的解决方案:
1)在遍历所有点时,先对它和它之后所有修改下标一致的点进行合并,再计算。这是比较稳妥的方法
2)在求最值等一些特殊的题目中(比如例1),重复累加并不影响操作,可以根据排序让它只有在同一个点都累加完后,才出现对答案有贡献的值
比如,求最大值。可以排序时先按照下标升序排序,再把-1操作排在+1前面,这样遍历时先减再加,不会影响最大值的求解。
3)使用万能的map。map就像一个桶数组一样,可以很方便地把所有点的修改都累加到一块去。还能自动按照键升序排序,绝对是为扫描线量身定做的梦想中的容器!
但这样虽然方便,会有因常数过大而超时的风险(map理论复杂度为O(nlogn),但这个log很大)
Code:
#include <bits/stdc++.h>
using namespace std;struct Node{int pos, add; // 位置pos,贡献addfriend bool operator < (Node p1, Node p2){ // 先按照位置升序排序,再按照贡献升序排序(减法要排在加法前面,不然会导致先加得大了,然后求max时答案出错)if(p1.pos != p2.pos) return p1.pos < p2.pos;return p1.add < p2.add;}
};void solve()
{int n;cin >> n;vector <Node> A;for(int i = 0, b, t; i < n; i ++){cin >> b >> t;A.push_back({b, 1});A.push_back({t, -1}); // 注意大炮的范围是[b,t),所以差分的-1应该在t位置上,而不是t+1}sort(A.begin(), A.end());int ans = 1, d = 0; // ans是答案,d是差分值for(auto it : A){d += it.add;ans = max(ans, d);}cout << ans << "\n";
}signed main()
{ios :: sync_with_stdio(false), cin.tie(0), cout.tie(0);solve();return 0;
}
例2
有 n n n 个点, m m m 个修改,每次修改都对[l,r]区间内的每个点+1。1<=n,l,r<=1e9 1<=m<=1e6 1<=a[i]<=1e6
求 Σcnt[i]*a[i] 其中cnt[i]表示点的值为i的个数,a[i]表示每个值为i的点对答案的贡献。
这道题需要求区间修改后n个点中每一个值的个数。
记得前面说过“同时,当前修改点和上一个修改点之间的所有数组元素,其值都是上一个修改点位置的累加变量”。
由此,能知道两个修改点之间的所有点的值,又可以容易地计算出两个修改点之间差了多少个点。就可以统计cnt数组了。(具体看代码里pre变量的使用)
但这道题的难点不在于扫描线,而是出题人……
1.不能给所有变量都开long long,这样会因为常数过大而超时(因为long long占8个字节,int占四个字节,所以long long平均每次运算次数都是int的两倍)
2.如果你图方便用map存储所有的修改点,以为这样就不用考虑重复的问题了。但抱歉,出题人也会卡
在OI赛制下,很少有人能注意到上面两个坑点。码风朴实,没有那么多花里胡哨的同学反而因为不用STL而占据优势。
Code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxm = 1e6 + 5;int n, m;
int a[maxm], cnt[maxm]; // cnt:记录个数的桶数组struct Node{int p, t; // 表示p位置的修改为tfriend bool operator < (Node p1, Node p2){return p1.p < p2.p;}
};
vector <Node> d; // 差分数组void solve()
{cin >> n >> m;for(int i = 1; i <= m; i ++) cin >> a[i];for(int i = 1, l, r; i <= m; i ++){cin >> l >> r;d.push_back({l, 1}); d.push_back({r + 1, -1}); // 进行差分}sort(d.begin(), d.end()); // 排序int pre = -1; // 上一个差分的点int ans = 0; // 累加变量for(int i = 0; i < d.size(); i ++){int pos = i;while(d[i].p == d[i + 1].p){ // 把同一个位置的所有修改都累加起来,这样便于统计答案d[pos].t += d[i + 1].t;++ i;}if(pre != -1){cnt[ans] += (d[pos].p - 1) - pre + 1; // 累加的答案区间是[pre,d[].p)}ans += d[pos].t; // 累加pre = d[pos].p; // 记录前一个端点}ll tot = 0;for(int i = 1; i <= 1e6; i ++){tot += 1LL * a[i] * cnt[i]; // 对于不存在的,cnt[i]一定=0,其不会被记录}cout << tot << '\n';
}signed main()
{ios :: sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);solve();return 0;
}
【困难】二维扫描线(计算几何)
先咕一下,等会了再补
https://blog.csdn.net/Zz_0913/article/details/135128515
End
感谢大家的观看!拜拜ヾ(•ω•`)o
推销个人洛谷账号:ylch,洛谷博客:YLCHUP
相关文章:

【2024最新】C++扫描线算法介绍+实战例题
扫描线介绍:OI-Wiki 【简单】一维扫描线(差分优化) 网上一维扫描线很少有人讲,可能认为它太简单了吧,也可能认为这应该算在差分里(事实上讲差分的文章里也几乎没有扫描线的影子)。但我认为&am…...

语言主要是一种交流工具,而不是思维工具?GPT5何去何从?
引言 在人工智能领域,特别是大语言模型(LLM)的发展中,语言和思维的关系一直是一个备受关注的话题。近期,麻省理工学院(MIT)在《Nature》杂志上发表了一篇题为《Language is primarily a tool f…...

传感器标定(三)激光雷达外参标定(lidar2ins)
一、数据采集 1、LiDAR 传感器的 LiDAR PCD 数据 2、来自 IMU 传感器的姿势文件 3、手动测量传感器之间外部参数初始值并写入的 JSON 文件 二、下载标定工具 //总的git地址: https://github.com/PJLab-ADG/SensorsCalibration git地址: https://githu…...

【漏洞复现】Crocus系统—Download 文件读取
声明:本文档或演示材料仅用于教育和教学目的。如果任何个人或组织利用本文档中的信息进行非法活动,将与本文档的作者或发布者无关。 一、漏洞描述 Crocus系统中的Download文件读取漏洞允许未经身份验证的攻击者通过特定请求读取系统上的任意文件。Crocu…...

游戏开发面试题1
说说对单例模式的了解 单例模式(Singleton Pattern)是一种设计模式,其目的是确保一个类只有一个实例,并提供一个全局访问点来访问该实例。这在某些情况下非常有用,比如需要一个唯一的配置管理器、日志记录器、或资源管…...

线程池笔记
笔记梳理 前言.PHONYC标准库头文件C/C通用或C特有头文件mkdirc_str()snprintfvsnprintfumaskopen函数可变参数列表va_startva_endfunctionalstatic_castpthread_cond_init_threads.emplace_backstd::bindstd::placeholdersThreadPool(const ThreadPool<T> &tp) dele…...

Go语言基础数据类型、变量及自增语法
本文内容为Go语言的基础数据类型、变量定义和赋值及自增语法介绍。 目录 基础数据类型 变量 先定义后赋值 定义时直接赋值 自动推导定义赋值 平行赋值 自增语法 总结 基础数据类型 int,int8 intl6, int32, int64 uint8... uint64 float32,float64 true/false 变量 …...

ES6-ES13符号:单双引号、变量的解构赋值、占位符 、字符串模版`${} `、扩展运算符...、?,??,_,||=,=,in
原型、this、闭包,for四类循环,ES6-14(2023)_es6-es14-CSDN博客 目录 查看ES版本 单双引号:无区别 变量的解构赋值:声明变量被数组/对象中的元素赋值 推荐用const,因为是从其他地方获取值 …...

【远景能源25届校招PI测评】题型深度解析与应试策略
摘要: 远景能源作为新能源行业的领军企业,其校园招聘备受瞩目。本文将深入分析25届远景能源校招的PI测评题型,为求职者提供全面的备考指南。 正文: 尊敬的求职者们,您是否正准备迎接远景能源的校招挑战?P…...

关于Qt Creator 使用Qt Quick的Design模式设置
关于使用Qt Quick的Design模式设置: 如描述所言: 如果使用Design模式打开qml文件失败显示如下: 首先确认自己是否安装了Qt Design Studio 如果安装了仍然不显示,则需要勾选下面三个地方才能用Design模式打开.ui.qml文件&#…...

Spring常见问题一:IOC和DI
IOC和DI IOC和DI之间到底是什么关系? 什么是依赖关系?依赖关系会带来什么问题?Spring是怎么来支持依赖注入的? 引言 在现代软件开发中,面向对象编程(OOP)已经成为主流编程范式。然而࿰…...

LabVIEW红外热波图像缺陷检
开发使用LabVIEW开发的红外热波图像缺陷检测系统。该系统结合红外热像仪、工业相机和高效的数据采集硬件,实现对工件表面缺陷的自动检测和分析。通过LabVIEW的强大功能,系统能够实时采集、处理和显示红外热波图像,有效提高了检测的精度和效率…...

c#与欧姆龙PLC通信——如何更改PLC的IP地址
前言 我们有时候需要改变欧姆龙Plc的ip地址,下图有两种更改方式,一种是已知之前Plc设置的Ip地址,还有一种是之前不知道Pl的Ip地址是多少,下面分别做介绍。 1、已知PLC的IP地址的情况下更改地址 假设已知PLC的Ip地址,比如本文中PLC的IP为192.168.1.2,我首先将电脑的IP地…...

[Spring Boot]定时任务因系统时间修改之后无法执行
问题描述 当Spring Boot启动时,当前时间为2024-01-01 00:00:00。 此时你创建了任务: 每10秒钟触发一次定时任务 Scheduled(cron "0/10 * * * * ? ") public void scheduledTask() { }此时你手动修改了系统时间,修改为2023-12-0…...

【棋盘上的战舰】python刷题记录
目录 小前言 思路: 上代码 lucky ending 小前言 经过漫长的停更周期-----1个月 我决定铁血回归!!! 思路: 两层for循环暴力最快了这种小小范围题,主要是第一行和第一列的边界处理,我分为…...

NoSQL 之Redis集群
Redis集群 主从复制 主从复制(Replication)是 Redis 中一种基本的高可用架构模式,适用于简单的读写分离需求和基本的故障恢复。在主从复制中,一个 Redis 主节点可以拥有多个从节点,主要特点包括: 角色定义&…...

ES13的4个改革性新特性
1、类字段声明 在 ES13 之前,类字段只能在构造函数中声明, ES13 消除了这个限制 // 之前 class Car {constructor() {this.color = blue;this.age = 2...

Flutter EasyRefresh:介绍与使用指南
什么是 Flutter EasyRefresh? Flutter EasyRefresh 是一个强大的下拉刷新和上拉加载组件,用于构建流畅且高效的 Flutter 应用程序。它提供了多种自定义配置和动画效果,使开发者可以轻松实现列表的刷新和加载功能。 主要功能 支持下拉刷新和…...

链表的回文结构(链表的中间节点+反转链表)
链表的回文结构 一.链表的中间节点思路1:暴力求解思路2:快慢指针 二.返回倒数第k个节点思路1:暴力求解思路2:快慢指针 三.反转链表思路1:头插法思路2:反转指针的指向 四.链表的回文结构思路1:利…...

汇编学习基础知识【记录】
前言 又是快乐的学习汇编的一天,时间如白驹过隙,抓紧时间,在学习能力最好的年纪多学习一些知识,朝着美好生活而奋斗!哈哈哈 参考文章: https://blog.csdn.net/Z_H_Z_0/article/details/106574292 知识补…...

【持续集成_06课_Jenkins高级pipeline应用】
一、创建项目选择pipeline的风格 它主要是以脚本(它自己的语言)的方式进行运行,一般由运维去做的事情,作为测试而言。了解即可。 --- 体现形式全部通过脚本去实现:执行之前(拉取代码)执行&…...

taro小程序terser-webpack-plugin插件不生效(vue2版本)
背景 最近在做公司内部的小程序脚手架,为了兼容老项目和旧项目,做了vue2taro,vue3taro两个模板,发现terser-webpack-plugin在vue2和vue3中的使用方式并不相同,同样的配置在vue3webpack5中生效,但是在vue2webpack4中就…...

games103作业2(未完)
PBD方法 首先是每个质点的力的分析,不考虑碰撞和弹簧弹力的情况下,每个质点受重力的影响,所以需要对每个质点进行速度和位置的重力影响更新。 float t 0.0333f; float damping 0.99f; int[] E; float[] L; Vector3[] V; Vector3 gra…...

避免 WebSocket 连接被拒绝
一、检查服务器配置和权限 (一)确认服务器访问权限 确保您的客户端有访问服务器的合法权限。如果服务器设置了访问控制列表(ACL)或仅允许特定的源(Origin)进行连接,您需要确保客户端的请求来源在允许的范围内。例如,如果服务器只允许来自特定域名的连接,而您的客户端从…...

shell中关于数组的使用
shell中关于数组的使用 在Shell中,数组是一种可以存储多个值的变量。数组的每个值都由一个数字索引来访问。在Shell中,数组的索引从0开始。 数组的常见的使用方法包括 数组的定义数组的打印数组长度数组的遍历数组元素的打印数组元素的添加数组元素的…...

python:绘制一元三次函数的曲线
编写 test_x3_3x.py 如下 # -*- coding: utf-8 -*- """ 绘制函数 y x^33x4 在 -3<x<3 的曲线 """ import numpy as np from matplotlib import pyplot as plt# 用于正常显示中文标题,负号 plt.rcParams[font.sans-serif] […...

SAP PP学习笔记26 - User Status(用户状态)的实例,订单分割中的重要概念 成本收集器,Confirmation(报工)的概述
上面两章讲了生产订单的创建以及生产订单的相关内容。 SAP PP学习笔记24 - 生产订单(制造指图)的创建_sap 工程外注-CSDN博客 SAP PP学习笔记25 - 生产订单的状态管理(System Status(系统状态)/User Status(用户状态)),物料的可用性检查,生…...

ctfshow-web入门-php特性(web104-web108)
目录 1、web104 2、web105 3、web106 4、web107 5、web108 1、web104 需要传入的 v1 和 v2 进行 sha1 加密后相等。 解法1: 这里都没有判断 v1 和 v2 是否相等,我们直接传入同样的内容加密后肯定也一样。 ?v21 post: v11 拿到 flag…...

python之集合相关
1.概况 是无序的数据结构 集合内的个体统称为元素,每个元素不可重复 所有元素被放在大括号里面,元素之间通过逗号分隔 集合对象是一组无序的可哈希的值,集合元素是不可变的数据类型 2.定义集合 使用大括号语法 基本语法: {元素1&a…...

【学习笔记】无人机(UAV)在3GPP系统中的增强支持(十一)-无人机服务可用性用例需求
引言 本文是3GPP TR 22.829 V17.1.0技术报告,专注于无人机(UAV)在3GPP系统中的增强支持。文章提出了多个无人机应用场景,分析了相应的能力要求,并建议了新的服务级别要求和关键性能指标(KPIs)。…...