【高阶数据结构】线段树加乘(维护序列)详细解释乘与加懒标记
文章目录
- 1.题目
- [AHOI2009] 维护序列
- 2.懒标记处理
- 先加后乘的形式
- 1. 先加后乘的操作
- 先乘后加的形式
- 2. 先乘后加的操作
- **乘法操作**
- **加法操作**
- 懒标记的下传
- 3.代码
1.题目
题目来源:https://www.luogu.com.cn/problem/P2023
[AHOI2009] 维护序列
题目背景
老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。
题目描述
有一个长为 n n n 的数列 { a n } \{a_n\} {an},有如下三种操作形式:
- 格式
1 t g c
,表示把所有满足 t ≤ i ≤ g t\le i\le g t≤i≤g 的 a i a_i ai 改为 a i × c a_i\times c ai×c ; - 格式
2 t g c
表示把所有满足 t ≤ i ≤ g t\le i\le g t≤i≤g 的 a i a_i ai 改为 a i + c a_i+c ai+c ; - 格式
3 t g
询问所有满足 t ≤ i ≤ g t\le i\le g t≤i≤g 的 a i a_i ai 的和,由于答案可能很大,你只需输出这个数模 p p p 的值。
输入格式
第一行两个整数 n n n 和 p p p。
第二行含有 n n n 个非负整数,表示数列 { a i } \{a_i\} {ai} 。
第三行有一个整数 m m m,表示操作总数。
从第四行开始每行描述一个操作,同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。
输出格式
对每个操作 3,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。
2.懒标记处理
先加后乘的形式
假设我们要在一个区间上做更新操作,区间内的某个数的值用 x x x 表示,add 和 mul 分别代表加法因子和乘法因子。
1. 先加后乘的操作
先加后乘的更新过程是:
我们想在区间上的每个元素先加一个数 a a a,再乘以一个数 m m m,这个操作可以表示为:
( x + add ) ∗ mul (x + \text{add}) * \text{mul} (x+add)∗mul
-
乘法更新
假设当前要在区间上乘以 a a a,则操作变成:
( x + add ) ∗ mul ∗ a (x + \text{add}) * \text{mul} * a (x+add)∗mul∗a
新的乘法标记将变为 mul ∗ a \text{mul} * a mul∗a,这是可以接受的。 -
加法更新
假设现在要在区间上加上 a a a,则变成:
( x + add ) ∗ mul + a (x + \text{add}) * \text{mul} + a (x+add)∗mul+a
这个表达式不容易简化成一种标准形式。我们可以尝试将其转换为:
( x + add + a mul ) ∗ mul (x + \text{add} + \frac{a}{\text{mul}}) * \text{mul} (x+add+mula)∗mul然而,这样得到的 add 标记变成了 add + a mul \text{add} + \frac{a}{\text{mul}} add+mula,这个值可能是一个小数,很难表示或处理。因此,先加后乘的形式并不理想。
先乘后加的形式
2. 先乘后加的操作
另一种常见的更新方式是先乘后加,即首先进行乘法操作,然后再进行加法操作。我们可以表示为:
x ∗ mul + add x * \text{mul} + \text{add} x∗mul+add
乘法操作
如果我们在这个数上乘以 m m m,则更新如下:
( x ∗ mul + add ) ∗ m = x ∗ mul ∗ m + add ∗ m (x * \text{mul} + \text{add}) * m = x * \text{mul} * m + \text{add} * m (x∗mul+add)∗m=x∗mul∗m+add∗m
因此:
- 新的乘法标记变成了 mul ∗ m \text{mul} * m mul∗m。
- 新的加法标记变成了 add ∗ m \text{add} * m add∗m。
加法操作
如果我们在这个数上加上 a a a,则更新如下:
x ∗ mul + add + a x * \text{mul} + \text{add} + a x∗mul+add+a
这里:
- 新的加法标记变为 add + a \text{add} + a add+a。
- 乘法标记保持不变。
懒标记的下传
考虑区间树的情况,假设父节点有乘法标记 m m m 和加法标记 a a a,其更新表达式为:
( x ∗ mul + add ) ∗ m + a = x ∗ mul ∗ m + add ∗ m + a (x * \text{mul} + \text{add}) * m + a = x * \text{mul} * m + \text{add} * m + a (x∗mul+add)∗m+a=x∗mul∗m+add∗m+a
-
左右孩子节点的
sum
更新为:
root.sum ∗ m + ( root.r − root.l + 1 ) ∗ a \text{root.sum} * m + (\text{root.r} - \text{root.l} + 1) * a root.sum∗m+(root.r−root.l+1)∗a
这是一个标准的加法和乘法更新,可以继续进行懒标记下传。 -
乘法标记(mul)下传时,更新为:
mul ∗ m \text{mul} * m mul∗m -
加法标记(add)下传时,更新为:
add ∗ m + a \text{add} * m + a add∗m+a
3.代码
//为什么先加后乘的形式不可以
//我们要变成(x+add)*mul的形式
//假设现在要在这个区间上乘 a
//那么这个数就变成了 (x+add)*mul*a
//新的mul标记就变成了 mul*a 这个是可以的
//假设现在要在这个区间上加 a
//那么这个数就变成了 (x+add)*mul + a
//化成上面的形式 (x+add + a/mul)*mul
//显然新的add标记(add+ a/mul)可能是个小数,不好表示,故而这种方式不合适//先乘后加形式
// x*mul +add的形式
// 在这个数上乘m
// (x*mul+add)*m
// x*mul*m + add*m
// 新的mul标记就变成了 mul*m
// 新的add标记就变成了 add*m
// 在这个数上加a
// x*mul + add + a
// mul标记不变
// 新的add标记就变成了 add + a
// pushdown的时候为什么l和r的懒标记怎么改
// 显然父亲结点的mul和add就是以先乘后加的形式下传
// 假设父亲结点为m和a
// (x*mul+add)*m+ a
// x*mul*m +add*m+a
// 左右孩子的 sum = (root.sum*m+(root.r-root.l+1)*add)
// mul : mul*m
// add : add*m+a#include <cstdio>
#include <iostream>
using namespace std;
#define int long long
typedef long long ll;
using LL =long long;
const int N = 1e5 + 10;
int n, p, m;
int w[N];
struct Node{int l, r, sum, add, mul;
} tr[4 * N];void pushup(int u)
{tr[u].sum = (tr[u<<1].sum+tr[u<<1|1].sum)%p;
}void cale(Node &root, int a, int m)
{root.sum = (ll)((ll)(root.sum)*m +(ll)(root.r-root.l + 1)*a)%p;root.add = (ll)(root.add*m+a)%p;root.mul = (ll)root.mul*m%p;
}void pushdown(int u)
{Node & root = tr[u],& left =tr[u<<1], &right =tr[u<<1|1];cale(left,root.add,root.mul);cale(right,root.add,root.mul);tr[u].add=0;tr[u].mul=1;
}void build(int u, int l, int r)
{if(l==r){tr[u]={l,r,w[l],0,1};}else{tr[u]={l,r,0,0,1};int mid = l+r>>1;build(u<<1,l,mid);build(u<<1|1,mid+1,r);pushup(u);}
}void modify(int u, int l, int r, int add, int mul)
{if(tr[u].l>=l&&tr[u].r<=r){cale(tr[u],add,mul);}else{pushdown(u);int mid =tr[u].l+tr[u].r>>1;if(l<=mid)modify(u<<1,l,r,add,mul);if(r >mid)modify(u<<1|1,l,r,add,mul);pushup(u);}
}int query(int u, int l, int r)
{if(tr[u].l>=l &&tr[u].r<=r)return tr[u].sum;else{pushdown(u);int mid =tr[u].l+tr[u].r>>1;ll res =0;if(l<=mid)res += query(u<<1,l,r)%p;if(r >mid)res = (res+query(u<<1|1,l,r))%p;return res;}
}signed main()
{cin>>n>>p;for(int i=1;i<=n;i++)cin>>w[i];build(1,1,n);cin>>m;while ( m -- ){int t, l, r, d;cin>>t>>l>>r;if ( t == 1 ) {cin>>d;modify(1, l, r, 0, d);}else if ( t == 2 ){cin>>d;modify(1, l, r, d, 1);}else cout<<query(1, l, r)<<'\n';}return 0;
}
相关文章:
【高阶数据结构】线段树加乘(维护序列)详细解释乘与加懒标记
文章目录 1.题目[AHOI2009] 维护序列 2.懒标记处理先加后乘的形式1. 先加后乘的操作 先乘后加的形式2. 先乘后加的操作**乘法操作****加法操作** 懒标记的下传 3.代码 1.题目 题目来源:https://www.luogu.com.cn/problem/P2023 [AHOI2009] 维护序列 题目背景 老师交给小可可…...
replaceState和vue的router.replace删除query参数的区别
使用history.replaceState /*** 替换当前的 history state和url* param {(searchParams:URLSearchParams)>any} cb*/ export const replaceUrlSearch (cb) > {// 获取当前 URLconst url new URL(window.location.href)// 获取 URL 的查询参数const searchParams new …...
[USACO14JAN] Ski Course Rating G
题目大意 滑雪场用一个 N ∗ M N*M N∗M 的整数矩阵表示海拔高度,每个整数表示一个范围在 1 0 9 10^9 109 的高度。每个格子都可以滑到相邻的格子,爱好者们将会在雪场种尽情享受。有些格子被指定为起点,每个起点都要进行评级以帮助爱好者选…...

初步认识 Neo4j 图数据库
Neo4j 是一种高性能的图数据库管理系统,基于图论设计,能够高效地存储和查询复杂的关系数据。以下是关于 Neo4j 的详细介绍: 核心特性 数据模型: Neo4j 使用图数据模型,将数据以节点(Node)、关系…...
Qt中容器 QVector、QList、QSet和QMap 性能与用途比较
表格汇总: 容器存储结构随机访问性能插入/删除性能主要用途QVector连续存储的动态数组 O ( 1 ) O(1) O(1)末尾: O ( 1 ) O(1) O(1),中间: O ( n ) O(n) O(n)频繁随机访问,末尾元素的添加/删除QList优化存储࿰…...

ASP.NET Core - 依赖注入(四)
ASP.NET Core - 依赖注入(四) 4. ASP.NET Core默认服务5. 依赖注入配置变形 4. ASP.NET Core默认服务 之前讲了中间件,实际上一个中间件要正常进行工作,通常需要许多的服务配合进行,而中间件中的服务自然也是通过 Ioc…...
数学用语中 up to 的含义
1. 问题 在数学用语中,常见到“up to”这种用法, 但这种用法与我们常规情况下的用法不同,常令人困惑。 2. “等价关系”说明 已知两个数学对象 a 和 b,以及实数域R, • 当 a 和 b是通过 R 关联的࿰…...
Spring Boot + MyBatis-Flex 配置 ProxySQL 的完整指南
✅ Spring Boot MyBatis-Flex 配置 ProxySQL 的完整指南 下面是一个详细的教程,指导您如何在 Spring Boot 项目中使用 MyBatis-Flex 配置 ProxySQL 进行 读写分离 和 主从同步 的数据库访问。 🎯 目标 在 Spring Boot 中连接 ProxySQL。使用 MyBatis-…...

WEB攻防-通用漏洞_XSS跨站_权限维持_捆绑钓鱼_浏览器漏洞
目录 XSS的分类 XSS跨站-后台植入Cookie&表单劫持 【例1】:利用beef或xss平台实时监控Cookie等凭据实现权限维持 【例2】:XSS-Flash钓鱼配合MSF捆绑上线 【例3】:XSS-浏览器网马配合MSF访问上线 XSS的分类 反射型(非持久…...

人工智能任务20-利用LSTM和Attention机制相结合模型在交通流量预测中的应用
大家好,我是微学AI,今天给大家介绍一下人工智能任务20-利用LSTM和Attention机制相结合模型在交通流量预测中的应用。交通流量预测在现代城市交通管理中是至关重要的一环,它对优化交通资源分配以及提升道路通行效率有着不可忽视的意义。在实际…...

Day04-后端Web基础——Maven基础
目录 Maven课程内容1. Maven初识1.1 什么是Maven?1.2 Maven的作用1.2.1 依赖管理1.2.2 项目构建1.2.3 统一项目结构 2. Maven概述2.1 Maven介绍2.2 Maven模型2.2.1 构建生命周期/阶段(Build lifecycle & phases)2.2.2 项目对象模型 (Project Object Model)2.2.3 依赖管理模…...

Hive SQL必刷练习题:留存率问题
首次登录算作当天新增,第二天也登录了算作一日留存。可以理解为,在10月1号登陆了。在10月2号也登陆了,那这个人就可以算是在1号留存 今日留存率 (今日登录且明天也登录的用户数) / 今日登录的总用户数 * 100% 解决思…...

虚拟同步机(VSG)Matlab/Simulink仿真模型
虚拟同步机控制作为原先博文更新的重点内容,我将在原博客的基础上,再结合近几年的研究热点对其内容进行更新。Ps:VSG相关控制方向的simulink仿真模型基本上都搭建出来了,一些重要的控制算法也完成了实验验证。 现在搭建出来的虚拟…...
单头注意力机制(SHSA)详解
定义与原理 单头注意力机制是Transformer模型中的核心组件之一,它通过模拟人类注意力选择的过程,在复杂的输入序列中识别和聚焦关键信息。这种方法不仅提高了模型的性能,还增强了其解释性,使我们能够洞察模型决策的原因。 单头注意力机制的工作流程主要包括以下几个步骤:…...

【漏洞分析】DDOS攻防分析
0x00 UDP攻击实例 2013年12月30日,网游界发生了一起“追杀”事件。事件的主角是PhantmL0rd(这名字一看就是个玩家)和黑客组织DERP Trolling。 PhantomL0rd,人称“鬼王”,本名James Varga,某专业游戏小组的…...

JavaScript动态渲染页面爬取之Splash
Splash是一个 JavaScript渲染服务,是一个含有 HTTP API的轻量级浏览器,它还对接了 Python 中的 Twisted 库和 OT库。利用它,同样可以爬取动态渲染的页面。 功能介绍 利用 Splash,可以实现如下功能: 异步处理多个网页的渲染过程:获取渲染后…...

慧集通(DataLinkX)iPaaS集成平台-系统管理之UI库管理、流程模板
UI库管理 UI库管理分为平台级和自建两种,其中平台级就是慧集通平台自己内置的一些ui库所有客户均可调用,自建则是平台支持使用者自己根据规则自己新增对应的UI库。具体界面如下: 自建UI库新增界面: 注:平台级UI库不支…...
OpenCV相机标定与3D重建(59)用于立体相机标定的函数stereoCalibrate()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 标定立体相机设置。此函数找到两个相机各自的内参以及两个相机之间的外参。 cv::stereoCalibrate 是 OpenCV 中用于立体相机标定的函数。它通过一…...

摄像头模块在狩猎相机中的应用
摄像头模块是狩猎相机的核心组件,在狩猎相机中发挥着关键作用,以下是其主要应用: 图像与视频拍摄 高清成像:高像素的摄像头模块可确保狩猎相机拍摄出清晰的图像和视频,能够捕捉到动物的毛发纹理、行为细节及周围环境的…...
ruoyi-cloud docker启动微服务无法连接nacos,Client not connected, current status:STARTING
ruoyi-cloud docker启动微服务无法连接nacos,Client not connected, current status:STARTING 场景 当使用sh deploy.sh base来安装mysql、redis、nacos环境后,紧接着使用sh deploy.sh modules安装微服务模块,会发现微服务无法连接nacos的情…...

C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...

2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...