当前位置: 首页 > news >正文

线段树多懒标记

最近在思考:如何对一个序列维护带有两种区间修改的多查询问题。这样不可避免地需要对两种修改操作分别维护一种懒标记。但显然,不能将两种懒标记独立看待,因为对于两种操作,先后顺序不同会造成不同的影响。因此如何处理两个懒标记之间的相互影响至关重要, \(pushdown\) 函数需要精心设计。

这里口胡两种情况(不一定对),阐述一下设计懒标记的原理。

区间加与区间乘

考虑两种操作的先后顺序:

  1. 先乘后加:直接进行即可
  2. 先加后乘:加的部分也需要乘,再作和
void pushdown(int p){if(tr[p].add == 0 && tr[p].mul == 1) return;tr[lc].sum = (tr[lc].sum * tr[p].mul) + tr[p].add * (tr[lc].r - tr[lc].l + 1);tr[rc].sum = (tr[rc].sum * tr[p].mul) + tr[p].add * (tr[rc].r - tr[rc].l + 1);// 先处理乘法懒标记,再处理加法懒标记tr[lc].mul = tr[lc].mul * tr[p].mul;tr[rc].mul = tr[rc].mul * tr[p].mul;tr[lc].add = tr[lc].add * tr[p].mul + tr[p].add;tr[rc].add = tr[rc].add * tr[p].mul + tr[p].add;tr[p].add = 0;tr[p].mul = 1;
}

区间加与区间赋值 (查询区间最大值)

// max
template<typename T>
struct SegTree
{struct Node{int l, r;T maxv, tag_fix, tag_add;}tr[maxn << 2];#define lc p<<1#define rc p<<1|1void pushup(int p){tr[p].maxv = max(tr[lc].maxv, tr[rc].maxv);}void pushdown(int p){if(tr[p].tag_fix != -1){tr[lc].maxv = tr[rc].maxv = tr[p].tag_fix; }if(tr[p].tag_add){tr[lc].maxv += tr[p].tag_add;tr[rc].maxv += tr[p].tag_add;}if(tr[p].tag_fix != -1){tr[lc].tag_fix = tr[rc].tag_fix = tr[p].tag_fix;tr[lc].tag_add = tr[rc].tag_add = 0;}if(tr[p].tag_add){tr[lc].tag_add += tr[p].tag_add;tr[rc].tag_add += tr[p].tag_add;}tr[p].tag_fix = -1;tr[p].tag_add = 0;}void build(int p, int l, int r,auto& arr){tr[p] = { l,r,arr[l],-1,0};if (l == r) return;int mid = l + r >> 1;build(lc, l, mid , arr);build(rc, mid + 1, r , arr);pushup(p);}void update_fix(int p, int l, int r, T k){if (l <= tr[p].l && tr[p].r <= r) {tr[p].maxv = k;tr[p].tag_fix = k;tr[p].tag_add = 0;return;}int mid = tr[p].l + tr[p].r >> 1;pushdown(p);if (l <= mid) update_fix(lc, l ,r, k);if (r > mid)  update_fix(rc, l ,r, k);pushup(p);}void update_add(int p, int l, int r, T k){if (l <= tr[p].l && tr[p].r <= r){tr[p].maxv += k;tr[p].tag_add += k;return;}int mid = tr[p].l + tr[p].r >> 1;pushdown(p);if (l <= mid) update_add(lc, l ,r, k);if (r > mid)  update_add(rc, l ,r, k);pushup(p);}T querymax(int p, int l, int r){if (l <= tr[p].l && tr[p].r <= r) return tr[p].maxv;pushdown(p);int mid = tr[p].l + tr[p].r >> 1;T maxv = INT_MIN;if (l <= mid) maxv = max(maxv, querymax(lc, l, r));if (r > mid) maxv = max(maxv, querymax(rc, l, r));return maxv;}};

线段树多懒标记设计相关例题:
ABC441 G
code

edu23 F
code

http://www.jsqmd.com/news/263961/

相关文章:

  • 智能风控平台 scalability 设计:AI应用架构师的经验分享
  • 【顶刊未发表】基于混沌增强领导者黏菌算法CELSMA复杂山地危险模型无人机路径规划附Matlab代码
  • GESP认证C++编程真题解析 | 202306 三级
  • Python+Vue的笔记管理系统的设计与实现 django Pycharm flask
  • Python+Vue的 美食分享论坛的设计和实现 django Pycharm flask
  • SpringBoot 全局异常处理
  • 计算机小程序毕设实战-基于springboot+微信小程序的服装商城的设计与实现小程序基于微信小程序的在线服装商城店铺的设计与实现【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • Python+Vue的 第三方物流管理系统 django Pycharm flask
  • STM32F03C8T6通过AT指令获取天气API-下篇
  • 2024最新大数据架构趋势:云原生与湖仓一体实战指南
  • RAG vs 微调:LLM优化双路径指南 + LLaMA-Factory Online高效落地
  • RoMa v2 - MKT
  • 小程序计算机毕设之基于springboot+微信小程序的服装购物平台的设计与实现小程序(完整前后端代码+说明文档+LW,调试定制等)
  • 吐血推荐10个一键生成论文工具,专科生毕业论文必备!
  • AArch64和X86下的函数调用 - Polaris
  • MCU单总线通信
  • 三维动态避障路径规划:基于部落竞争与成员合作算法(CTCM)融合动态窗口法DWA的无人机三维动态避障方法研究附MATLAB代码
  • 诺特定理:世界是二阶导的吗?
  • GESP认证C++编程真题解析 | 202306 四级
  • 洛谷 P11606 [PA 2016] 构树 / Reorganizacja - Rye
  • CPU占用高排查
  • GESP认证C++编程真题解析 | 202303 二级
  • GESP认证C++编程真题解析 | 202303 二级
  • [豪の算法奇妙冒险] 代码随想录算法训练营第三十一天 | 56-合并区间、738-单调递增的数字
  • MATLAB表格数据处理的项目落地经验(避坑+效率提升)
  • 最新论文 | EarthVL: 武大钟燕飞团队提出渐进式理解/生成框架, 从识别到深度理解遥感地物, 提供专业决策建议 - MKT
  • Flutter × OpenHarmony 跨端开发之汇率转换与汇率卡片展示
  • 《卷一》人形机器人导论:从机械设计到系统集成
  • (1-1)人形机器人的发展历史、趋势与应用场景:人形机器人的发展历程
  • 优雅汇率:Flutter × OpenHarmony 跨端汇率转换计算器实现