可持久化线段树小结

学了可持久化线段树有一段时间了,一直没拿出时间来整理一下,刚好今天有空,就写一写。

可持久化的含义是对于每次修改操作都将产生一个新版本的线段树,并且旧版本的线段树仍然保留可以随时访问。

基于这个目的,我们可以采用类似动态开点的方法构建一颗线段树。
假设我们已经有了一个版本的线段树,我们要对这个线段树进行操作,我们首先复制前一颗线段树的根节点,然后在执行修改操作的时候,把所有途经的节点全部新建,其他节点保留。

一、包含单点修改,区间查询的可持久化线段树的实现

struct persist_segtree{struct Node{ //线段树的节点int lft,rgt; //左儿子指针和右儿子指针int num; //当前节点保存的值}segs[maxn];int rt[maxn]; //历史版本的线段树根节点指针int tot; //节点数目void init(){tot = 0;memset(segs,0,sizeof(segs));}inline int getnum(int rt){return rt?segs[rt].num:0;}void add(int &rt,int lft,int rgt,int pos,int num){ //修改操作int nrt = ++tot; //沿途的节点都要新建segs[nrt] = segs[rt]; //新建的节点是原节点的拷贝,然后再修改rt = nrt; int mid = (lft + rgt)/2;if(lft == rgt){ //如果到达底部segs[rt].num += num;return ;}if(pos <= mid) //如果要修改的位置在左侧add(segs[rt].lft,lft,mid,pos,num);else //如果要修改的位置在右侧add(segs[rt].rgt,mid+1,rgt,pos,num);segs[rt].num = getnum(segs[rt].lft) + getnum(segs[rt].rgt); //更新本节点的值}int query(int rt,int lft,int rgt,int beg,int end){if(!rt) return 0;if(beg <= lft && rgt <= end) return segs[rt].num;if(beg > rgt || end < lft) return 0;int mid = (lft + rgt)/2;return query(segs[rt].lft,lft,mid,beg,end) + query(segs[rt].rgt,mid+1,rgt,beg,end);}
}

1、查询,比如要查询第5个版本线段树的[3,199919991999]的区间和,那么查询语句可以这样写:

segtree.query(segtree.rt[5],1,1000000000,3,199919991999);

2、修改,比如在201720172017位置插入数值12345:

segtree.rt[t] = segtree.rt[t-1];
segtree.add(segtree.rt[t],1,1000000000,201720172017,12345);

二、区间修改

我也不知道为什么要把区间修改列在这里,其实区间修改就是lazy标记,和普通的线段树没有什么区别,有一点需要注意,就是在 标记下传 的时候,也要新建节点。
	/*标记下传*//*注意在标记下传的时候也要新开节点*/void down(int rt,int lft,int rgt){if(!segs[rt].lazy) return ;int mid = (lft + rgt)/2;segs[++tot] = segs[segs[rt].lft];segs[tot].num += segs[rt].lazy*(mid-lft+1);segs[tot].lazy += segs[rt].lazy;segs[rt].lft = tot;segs[++tot] = segs[segs[rt].rgt];segs[tot].num += segs[rt].lazy*(rgt-mid);segs[tot].lazy += segs[rt].lazy;segs[rt].rgt = tot;segs[rt].lazy = 0;}

查询和修改操作也要根据lazy标记做适当的修改

    void add(int &rt,int lft,int rgt,int beg,int end,int num){int nrt = ++tot;segs[nrt] = segs[rt];rt = nrt;int mid = (lft + rgt)/2;if(beg <= lft && rgt <= end){segs[rt].num += (rgt-lft+1)*num;segs[rt].lazy += num;return ;}if(rgt < beg || end < lft) return ;down(rt,lft,rgt);if(lft <= end) add(segs[rt].lft,lft,mid,beg,end,num);if(rgt >= beg) add(segs[rt].rgt,mid+1,rgt,beg,end,num);segs[rt].num = getnum(segs[rt].lft) + getnum(segs[rt].rgt);}int query(int rt,int lft,int rgt,int beg,int end){if(!rt) return 0;if(beg <= lft && rgt <= end) return segs[rt].num;if(beg > rgt || end < lft) return 0;int mid = (lft + rgt)/2;down(rt,lft,rgt);return query(segs[rt].lft,lft,mid,beg,end) + query(segs[rt].rgt,mid+1,rgt,beg,end);}

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

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

相关文章

【动态规划】 数字游戏 (ssl 1653)

数字游戏 题目大意&#xff1a; 有n个数&#xff0c;分别为a[1] (序号为1),a[2] (序号为2),a[3]…a[n]&#xff0c;让你选m个数&#xff0c;每选一个数&#xff0c;就要减去已选个数(不算当前数)*b[i] (i为当前值的序号)&#xff0c;所选数的最大值(要减去相应的b) 原题 小…

.NET Core玩转机器学习

ML.NET 专门为.NET开发者提供了一套跨平台的开源的机器学习框架。ML.NET支持.NET开发者不需要过度专业的机器学习开发经验&#xff0c;就能轻松地训练自己的模型&#xff0c;并且嵌入到自己的应用中。一切尽在.NET之中。ML.NET早期是由Microsoft Research开发&#xff0c;近十年…

P2900-[USACO08MAR]Land AcquisitionG【斜率优化】

正题 题目链接:https://www.luogu.com.cn/problem/P2900 题目大意 nnn块hi∗wih_i*w_ihi​∗wi​的土地&#xff0c;购买一组土地需要max(h)∗max(w)max(h)*max(w)max(h)∗max(w)&#xff0c;求购买所有土地的最小费用。 解题思路 首先如果hhh和www都小于另一块土地显然是不需…

二元运算 FFT+分治

题目&#xff1a; 4836: [Lydsy2017年4月月赛]二元运算 Time Limit: 8 Sec Memory Limit: 128 MB Submit: 486 Solved: 162 [Submit][Status][Discuss] Description 定义二元运算 opt 满足 现在给定一个长为 n 的数列 a 和一个长为 m 的数列 b &#xff0c;接下来有 q 次询问。…

【记忆化搜索】【线性化DP】滑雪 (ssl 1202/luogu 1434/pku 1088)

滑雪滑雪滑雪 ssl 1202 luogu 1434 pku 1088 题目大意&#xff1a; 有一个N*M的矩阵&#xff0c;每个位置都有一个数&#xff0c;可以从大的数走向小的数&#xff0c;问可走的路最长是多少 原题 Michael喜欢滑雪百这并不奇怪&#xff0c; 因为滑雪的确很刺激。可是为了获…

POJ2942-Knights of the Round Table【tarjan】

正题 题目链接:http://poj.org/problem?id2942 题目大意 有nnn个骑士&#xff0c;有mmm组讨厌关系&#xff0c;要求讨厌的不能坐相邻&#xff0c;而且要求每次会有都有奇数个人&#xff0c;求有多少个骑士一组会议都不能参加。 解题思路 首先构一个补图&#xff0c;然后求有…

UVA4671 K-neighbor substrings FFT+字符串hash

题解&#xff1a; 将字符串A、B中的a和b分别以1和-1表示&#xff0c;对字符串B进行反转。 将A和B看成多项式&#xff0c;求卷积&#xff0c;这样的话从结果区间的[lenB−1,lenA)[lenB−1,lenA)中的每一个点的值valval&#xff0c;(lenB−val)/2(lenB−val)/2代表当前位置的字串…

微软Build 2018展示Visual Studio功能:跨系统云编程

5 月 8 日凌晨消息&#xff0c;微软 Build 2018 开发者大会在今天正式来开帷幕。很明显整场发布会被分为了上下两个部分&#xff0c;上半场如果说是聊一些技术实现和愿景&#xff0c;那下半场就应该说是实战说明了。跨平台云端编程了解下微软在现场展示了 Visual Studio&#x…

【DP】花店橱窗布置 (ssl 1626/luogu 1854)

花店橱窗布置花店橱窗布置花店橱窗布置 ssl 1626 luogu 1854 题目大意&#xff1a; 有n朵花和m个花瓶&#xff0c;每一朵花插在不同的花瓶里会有不同的美丽度&#xff0c;花瓶和花必须按原来的顺序摆放&#xff0c;求最大的美丽值 Description 假设你想以最美观的方式布置…

P4819-[中山市选]杀人游戏【tarjan】

正题 题目链接:https://www.luogu.com.cn/problem/P4819 题目大意 nnn个人&#xff0c;一个杀手&#xff0c;搜查一个平民可以知道他认识的人的身份&#xff0c;搜查杀手就会死&#xff0c;求最优情况下警察的最低死亡概率。 解题思路 先用tarjantarjantarjan搜出强连通&…

hdu4609 3idiots 三角形计数 FFT

直接上代码 #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> using namespace std; double pi acos(-1.0); struct complex{double re,im;complex(double r 0.0,double i 0.0):re(r),im(i…

利用Skywalking-netcore监控你的应用性能

SkywalkingSkyWalking开源项目由吴晟于2015年创建&#xff0c;同年10月在GitHub上作为个人项目开源。SkyWalking项目的核心目标&#xff0c;是针对微服务、Cloud Native、容器化架构&#xff0c;提供应用性能监控&#xff08;APM&#xff09;和分布式调用链追踪能力。2017年11月…

【背包】逃亡的准备 (ssl 1236)

逃亡的准备逃亡的准备逃亡的准备 ssl 1236 类似一样题目&#xff08;除数组范围外&#xff09;:ssl 2289&#xff08;庆功会&#xff09; 题目大意&#xff1a; 有n个物品&#xff0c;每个物品可以选l[i]个,每个的代价为a[i],价值为b[i]&#xff0c;在代价不大于m的情况下&a…

P3648-[APIO2014]序列分割【斜率优化】

正题 题目链接:https://www.luogu.com.cn/problem/P3648 题目大意 nnn个数字的序列&#xff0c;分割kkk次&#xff0c;每次的权值是左右两块数字的乘积。求最大权值和分割方案。 解题思路 显然分割顺序不会影响结果&#xff0c;一个分割方式的答案是每一块与其他块的乘积之和…

codeforces E. Jamie and Tree LCA+dfs序+线段树

题解&#xff1a; 写起来还稍微有点麻烦。 dfs序线段树可以维护子树的整体修改和查询。 因此&#xff0c;这道题我们要往子树上靠。 我们首先从1号点进行dfs遍历&#xff0c;顺便求出点的dfs序和深度&#xff0c;然后我们采用倍增的思想&#xff0c;可以预处理出每个点的祖先…

async/await 的基本实现和 .NET Core 2.1 中相关性能提升

前言这篇文章的开头&#xff0c;笔者想多说两句&#xff0c;不过也是为了以后再也不多嘴这样的话。在日常工作中&#xff0c;笔者接触得最多的开发工作仍然是在 .NET Core 平台上&#xff0c;当然因为团队领导的开放性和团队风格的多样性&#xff08;这和 CTO 以及主管的个人能…

【DP】砝码称重 (ssl 1072)

砝码称重 ssl 1072 题目大意&#xff1a; 有6种砝码&#xff0c;每种的个数分别为a1,a2,a3,a4,a5,a6,请问可以平出多少种重量(0除外) Description 设有1g、2g、3g、5g、10g、20g的砝码各若干枚&#xff08;其总重<1000&#xff09;&#xff0c; 要求&#xff1a; 输入…

P5025-[SNOI2017]炸弹【tarjan,线段树优化建图】

正题 题目链接:https://www.luogu.com.cn/problem/P5025 题目大意 .nnn个炸弹&#xff0c;每个在xxx位置处&#xff0c;范围为rrr。定义fif_ifi​表示第iii个炸弹爆炸能连锁的炸弹数&#xff0c;要求输出∑i1nfi∗i\sum_{i1}^nf_i*ii1∑n​fi​∗i 解题思路 将每个炸弹可以炸…

使用Swashbuckle构建RESTful风格文档

本次和大家分享的是Swagger to WebApi的nuget包Swashbuckle&#xff1b;因为项目需要统一api文档的风格&#xff0c;并要支持多种开发语言&#xff08;C#&#xff0c;java&#xff0c;python&#xff09;&#xff0c;所以首先想到的是swagger来构建api文档&#xff0c;本章讲解…

【dfs】【bfs】【链表】 求连通分量 (ssl 1759)

求连通分量 ssl 1759 题目大意 由n个点组成的无向图&#xff0c;求连通在一起的点数最大是多少 原题 求一个图的连通分量 Input n 顶点数(<100) 边 Output 连通分量 Sample Input 8 6 3 1 2 2 5 5 4 4 1 8 7 0 0 Sample Output 4 方法一&#xff08;dfs …