【题解】可持久化区间仿射区间和(Persistent Range Affine Range Sum)
很好小朋友们我们被要求写一个可持久化线段树支持区间修改、区间复制和输出区间和。懒标记是必须的但可持久化线段树一般不太支持 pushdown尤其在本题中。在进入子节点之前我们需要克隆当前节点因为当前节点可能被其他版本共享。然后才能将其懒标记下推到新克隆出的子节点最后将当前节点的懒标记重置。这样会导致不必要的新节点开销。于是我们不考虑 pushdown而是在递归函数中同时传进祖先变化即懒标记。线段树维护五个参数分别是左右子节点、区间总和 b、c 懒标记。1处理操作 0我们构建一个 change 函数对版本 p 的区间 [l, r] 施加变换 x - b*x c返回新版本的根节点。可持久化的精髓是“改了才新建”编写时请注意祖先变化的传递。2处理操作 1一个个复制绝对是不明智的我们可以先构建一个 crossover 函数。合并两个版本 x 和 y返回一个新版本其前 at 个元素来自 x后 len - at 个元素来自 y。这样题目的 [l, r] 可以变成先处理 [1, r] 的复制接着把原来的 [1, l - 1] 复制回去。3处理操作 2正常的 query 函数即可。另注意本题的边界和 base 十分复杂我用的是统一 base-1。#include bits/stdc.h using namespace std; typedef long long LL; const LL P 998244353; // 模数 const int N 1e5 10; // 数组最大长度 #define lc(p) tr[p].lc // 左孩子下标 #define rc(p) tr[p].rc // 右孩子下标 #define MID ((L R) 1) // 当前区间中点 /* 线段树节点结构 lc, rc : 左右孩子指针下标 sum : 当前节点代表的区间和已应用该节点的懒标记 lazy_b, lazy_c : 懒标记表示对子区间施加的仿射变换 x - lazy_b * x lazy_c */ struct node { int lc, rc; LL sum; LL lazy_b, lazy_c; }; vectornode tr; // 动态存储所有节点0 号节点为空节点 LL a[N]; // 原始数组1‑based // 新建一个节点懒标记初始为恒等变换 (1, 0) int newd() { tr.push_back({0, 0, 0, 1, 0}); return (int)tr.size() - 1; } // 克隆节点 p复制其所有信息 int clone_node(int p) { tr.push_back(tr[p]); return (int)tr.size() - 1; } /* 将仿射变换 x - b*x c 应用到节点 p 所代表的整个区间长度为 len 同时更新该节点的懒标记使其与原有懒标记复合。 注意应用顺序为 新变换 作用于 旧变换即最终变换为 b*(old(x)) c。 */ void modify(int p, LL b, LL c, LL len) { if (p 0) return; tr[p].sum (b * tr[p].sum c * len) % P; tr[p].lazy_b b * tr[p].lazy_b % P; tr[p].lazy_c (b * tr[p].lazy_c % P c) % P; } // 复合变换返回 g(f())即先 f 后 g pairLL, LL compose(LL g_b, LL g_c, LL f_b, LL f_c) { return { (g_b * f_b) % P, (g_b * f_c g_c) % P }; } // 用左右子树的 sum 更新当前节点的 sum void pushup(int p) { tr[p].sum (tr[lc(p)].sum tr[rc(p)].sum) % P; } // 建树p 为引用返回根节点下标 void build(int p, int L, int R) { p newd(); if (L R) { tr[p].sum a[L] % P; return; } build(lc(p), L, MID); build(rc(p), MID 1, R); pushup(p); } /* 对版本 p 的区间 [l, r] 施加变换 x - b*x c返回新版本的根节点。 参数 prop_b, prop_c 表示从根到当前节点路径上所有祖先懒标记复合后的变换 需要在访问当前区间时应用。 本函数采用路径复制只修改必要的节点保留未修改部分。 */ int change(int p, int L, int R, int l, int r, LL b, LL c, LL prop_b, LL prop_c) { // 完全不相交克隆当前节点并应用祖先变换然后返回 if (r L || R l) { int np clone_node(p); modify(np, prop_b, prop_c, R - L 1); return np; } // 完全覆盖克隆当前节点整体施加 “祖先变换 当前变换” if (l L R r) { auto t compose(b, c, prop_b, prop_c); // 先 prop后 (b,c) int np clone_node(p); modify(np, t.first, t.second, R - L 1); return np; } // 部分重叠创建新节点懒标记为恒等 int np newd(); // 传递给子节点的祖先变换 prop ∘ p.lazy先 p.lazy后 prop auto t compose(prop_b, prop_c, tr[p].lazy_b, tr[p].lazy_c); // 左子区间有重叠递归处理 if (l MID) { lc(np) change(lc(p), L, MID, l, r, b, c, t.first, t.second); } else { // 左子区间没有重叠克隆并应用祖先变换 if (lc(p) ! 0) { int lc clone_node(lc(p)); modify(lc, t.first, t.second, MID - L 1); lc(np) lc; } } // 右子区间有重叠递归处理 if (r MID 1) { rc(np) change(rc(p), MID 1, R, l, r, b, c, t.first, t.second); } else { if (rc(p) ! 0) { int rc clone_node(rc(p)); modify(rc, t.first, t.second, R - (MID 1) 1); rc(np) rc; } } pushup(np); return np; } // 封装 update - change初始祖先变换为恒等 int update(int p, int L, int R, int l, int r, LL b, LL c) { return change(p, L, R, l, r, b, c, 1, 0); } /* 合并两个版本 x 和 y返回一个新版本其前 at 个元素来自 x后 len - at 个元素来自 y。 参数 xb,xc 和 yb,yc 分别为两个版本当前需要应用的祖先变换。 具体规则 - at 0 全部取 y - at len 全部取 x - 否则根据 at 与左子树长度的关系递归处理左右子树。 */ int crossover(int x, int y, int len, int at, LL xb, LL xc, LL yb, LL yc) { if (at 0) { // 全部来自 y if (y 0) return 0; int ny clone_node(y); modify(ny, yb, yc, len); return ny; } if (len at) { // 全部来自 x if (x 0) return 0; int nx clone_node(x); modify(nx, xb, xc, len); return nx; } int midl (len 1) 1; // 左子树长度尽量平衡 // 为啥是上取整len R - L 1 // MID (R L) / 2 // midl MID - L 1 // 2 * midl R L - 2 * L 2 * 1 // midl R - L 1 LL nx_b, nx_c, ny_b, ny_c; // 将 x 的祖先变换与其自身懒标记复合得到传递给左/右子树的变换 if (x ! 0) { auto res compose(xb, xc, tr[x].lazy_b, tr[x].lazy_c); nx_b res.first; nx_c res.second; } else { nx_b xb; nx_c xc; } if (y ! 0) { auto res compose(yb, yc, tr[y].lazy_b, tr[y].lazy_c); ny_b res.first; ny_c res.second; } else { ny_b yb; ny_c yc; } int left_x (x 0) ? 0 : lc(x); int left_y (y 0) ? 0 : lc(y); int right_x (x 0) ? 0 : rc(x); int right_y (y 0) ? 0 : rc(y); // 左子树需要的前 at 个元素来自 x int lc crossover(left_x, left_y, midl, at, nx_b, nx_c, ny_b, ny_c); // 右子树需要的前 at - midl 个元素来自 x int rc crossover(right_x, right_y, len - midl, at - midl, nx_b, nx_c, ny_b, ny_c); int res newd(); lc(res) lc; rc(res) rc; pushup(res); return res; } /* 操作 1 的封装将版本 y 的区间 [l, r] 复制到版本 x 的对应位置。 通过两次交叉实现 1. tmp x[0 : l - 1] y[l : n] 2. 结果 tmp[0 : r] x[r : n] x[0 : l - 1] y[l : r] x[r : n] */ int update_crossover_twice(int x, int y, int l, int r, int total_len) { int tmp crossover(x, y, total_len, l - 1, 1, 0, 1, 0); return crossover(tmp, x, total_len, r, 1, 0, 1, 0); } /* 查询版本 p 中区间 [l, r] 的和。 参数 b, c 表示当前路径上所有祖先懒标记复合后的变换 在完全覆盖时直接应用到当前节点的 sum 上。 */ LL query(int p, int L, int R, int l, int r, LL b, LL c) { if (r L || R l) { return 0; } if (l L R r) { return (b * tr[p].sum c * (R - L 1)) % P; } // 传递给子节点的祖先变换 (b,c) ∘ p.lazy先 p.lazy后当前祖先 auto t compose(b, c, tr[p].lazy_b, tr[p].lazy_c); LL res 0; res query(lc(p), L, MID, l, r, t.first, t.second); res query(rc(p), MID 1, R, l, r, t.first, t.second); return res % P; } int main() { ios::sync_with_stdio(false); cin.tie(0); int n, Q; cin n Q; for (int i 1; i n; i ) cin a[i]; tr.reserve(20000000); // 预留节点空间 tr.push_back({0, 0, 0, 1, 0}); // 0 号节点作为空节点 int rt; build(rt, 1, n); vectorint roots(Q 1); // roots[i] 存储版本 A_i 的根节点 roots[0] rt; // 初始版本 A_{-1} for (int i 1; i Q; i) { int opt; cin opt; // 输入中 k, s 为 0‑based 版本编号-1 表示初始版本所以用 k1 索引 roots if (opt 0) { // 区间仿射变换 int k, l, r; LL b, c; cin k l r b c; l ; // 输入区间为 [l, r) 的 0‑based 下标转为 1‑based int src roots[k 1]; roots[i] update(src, 1, n, l, r, b, c); } else if (opt 1) { // 区间从另一版本复制 int k, s, l, r; cin k s l r; l ; int src_k roots[k 1]; int src_s roots[s 1]; roots[i] update_crossover_twice(src_k, src_s, l, r, n); } else { // 区间求和查询 int k, l, r; cin k l r; l ; int src roots[k 1]; cout query(src, 1, n, l, r, 1, 0) \n; roots[i] roots[i - 1]; } } return 0; }

相关新闻

告别手速焦虑:5分钟掌握大麦抢票脚本终极指南

告别手速焦虑:5分钟掌握大麦抢票脚本终极指南

告别手速焦虑:5分钟掌握大麦抢票脚本终极指南 【免费下载链接】DamaiHelper 大麦网演唱会演出抢票脚本。 项目地址: https://gitcode.com/gh_mirrors/dama/DamaiHelper 还在为抢不到心仪演唱会门票而烦恼吗?DamaiHelper是一个基于Python和Seleniu…

2026/8/12 22:13:45 阅读更多 →
ProxySQL源码编译常见问题与解决方案

ProxySQL源码编译常见问题与解决方案

1. ProxySQL编译报错问题解析 最近在尝试从源码编译ProxySQL时遇到了几个典型的编译错误。作为一款高性能的MySQL中间件,ProxySQL的编译过程确实比普通应用要复杂一些,特别是当开发环境配置不完整时,各种依赖问题就会接踵而至。下面我将分享几…

2026/8/12 22:13:45 阅读更多 →
mcp-gsc安全最佳实践:保护你的GSC数据和API凭证

mcp-gsc安全最佳实践:保护你的GSC数据和API凭证

mcp-gsc安全最佳实践:保护你的GSC数据和API凭证 【免费下载链接】mcp-gsc Google Search Console Insights with Claude AI for SEOs 项目地址: https://gitcode.com/gh_mirrors/mc/mcp-gsc mcp-gsc作为一款结合Google Search Console Insights与Claude AI的…

2026/8/12 22:13:45 阅读更多 →

最新新闻

3步实现实时音频降噪:DeepFilterNet新手也能快速上手的完整指南

3步实现实时音频降噪:DeepFilterNet新手也能快速上手的完整指南

3步实现实时音频降噪:DeepFilterNet新手也能快速上手的完整指南 【免费下载链接】DeepFilterNet Noise supression using deep filtering 项目地址: https://gitcode.com/GitHub_Trending/de/DeepFilterNet 你是否曾被在线会议中的键盘敲击声、空调噪音或街道…

2026/8/12 23:01:32 阅读更多 →
Spring Boot 2.7.0入门实战:从零搭建可部署的Java后端服务

Spring Boot 2.7.0入门实战:从零搭建可部署的Java后端服务

1. 项目概述:为什么是Spring Boot 2.7.0?如果你刚接触Java后端开发,或者是从传统的SSH、SSM框架迁移过来,听到“Spring Boot”这个词大概率会感到既熟悉又陌生。熟悉是因为它基于Spring,陌生是它似乎把很多复杂的东西都…

2026/8/12 23:01:32 阅读更多 →
指南:计算机考研408数据结构终极复习资源与高效学习路径推荐

指南:计算机考研408数据结构终极复习资源与高效学习路径推荐

指南:计算机考研408数据结构终极复习资源与高效学习路径推荐 【免费下载链接】cs-408 计算机考研专业课程408相关的复习经验,资源和OneNote笔记 项目地址: https://gitcode.com/GitHub_Trending/cs/cs-408 本文为你提供计算机考研408数据结构科目…

2026/8/12 23:01:32 阅读更多 →
Node 后端实战 · 为什么用 Cloudflare Workers + D1 扛起了整个多租户 SaaS 后端?架构决策全景复盘

Node 后端实战 · 为什么用 Cloudflare Workers + D1 扛起了整个多租户 SaaS 后端?架构决策全景复盘

Node 后端实战 为什么用 Cloudflare Workers D1 扛起了整个多租户 SaaS 后端?架构决策全景复盘 各位看官,这篇聊聊我最近做的一个多租户 SaaS 后端。技术栈没有走"买服务器、装 Postgres、再配 Nginx"的传统路线,而是选了 Cloud…

2026/8/12 23:01:32 阅读更多 →
从零实现DDPM:PyTorch实战扩散模型核心原理与UNet架构

从零实现DDPM:PyTorch实战扩散模型核心原理与UNet架构

1. 项目概述:从零构建DDPM的动机与价值最近在复现一些经典的生成模型,发现Denoising Diffusion Probabilistic Models(DDPM)虽然论文公式看着有点唬人,但当你真正动手把它从零搭出来,会发现其背后的思想异常…

2026/8/12 23:01:32 阅读更多 →
全面解决Visual C++运行库依赖问题:vcredist AIO一键智能安装方案

全面解决Visual C++运行库依赖问题:vcredist AIO一键智能安装方案

全面解决Visual C运行库依赖问题:vcredist AIO一键智能安装方案 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经在打开游戏或专业软件时&a…

2026/8/12 23:00:32 阅读更多 →

日新闻

Ubuntu 22.04安装与使用tree命令:高效管理Linux目录结构

Ubuntu 22.04安装与使用tree命令:高效管理Linux目录结构

1. 为什么需要一个“目录树”工具?在Linux世界里,尤其是Ubuntu这样的发行版,命令行是很多人的主战场。我们每天都要和文件、目录打交道。ls命令是查看目录内容的首选,它简洁、高效,能列出文件名、权限、大小等关键信息…

2026/8/12 9:33:34 阅读更多 →
博思AI智能体:意图识别、思考链与性能优化的工程实践

博思AI智能体:意图识别、思考链与性能优化的工程实践

在AI应用从“能用”走向“好用”的进程中,系统的响应速度、决策透明度与高并发稳定性是决定用户体验的关键。博思AI智能体近期完成了一次重要的专项优化,聚焦于意图识别、思考链展示与全链路压测三大核心领域,将系统从功能实现推向了工程卓越…

2026/8/12 9:33:34 阅读更多 →
子代理架构:AI智能体任务分解与协同执行的核心原理与实践

子代理架构:AI智能体任务分解与协同执行的核心原理与实践

1. 项目概述:为什么我们需要“子代理”?最近在折腾各种AI应用和自动化流程时,我越来越频繁地遇到一个瓶颈:单个AI智能体(Agent)的能力边界。无论是处理复杂的多步骤任务,还是需要同时调用多个专…

2026/8/12 9:33:34 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/12 1:11:09 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/12 1:11:09 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/12 1:11:08 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/11 17:09:45 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/12 1:11:10 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/11 17:09:45 阅读更多 →