[算法学习笔记] 可持久化栈

news/2024/7/6 20:35:06/文章来源:https://www.cnblogs.com/SXqwq/p/18275222

前置知识

可持久化,即对于每次更改,我们都期望记录它的历史信息。容易进行可持久化的数据结构通常满足 修改数据结构是,数据结构本身的拓扑序没有改变。,即形态没有改变。例如线段树,Trie 树,数组都可以容易地进行可持久化。

可持久化线段树前面已经讲过,见 算法学习笔记 线段树。

在阅读本文前, 建议读者了解手写栈和链表操作。

概述

可持久化栈是一种支持 栈顶修改,回退历史版本,栈顶查询 的一种数据结构。由于手写栈依赖于数组,我们可以用可持久化数组解决问题。这样我们可以随机访问栈中元素。但很多情况下我们没有这种需求。省去随机访问需求后的可持久化栈可以做到单次修改时间复杂度 \(O(1)\),空间复杂度 \(O(n)\)。线性时间内就可以解决问题。

实现

原理非常简单,每次入栈我们存档,记录当前版本号所对应的栈顶元素。容易发现,多个版本串联起来就组成了我们的栈。类似于链表结构。

这里我们通过画图举例。

image

如图,我们有一个大小为 \(8\) 的栈,只不过这里将栈横过来了。依次入栈 \(1-8\)。类似于链表,我们记录每个节点的前驱。这样就把节点串起来了。如果想要删除,退回到前驱即可。如果想要回退到任意版本,我们记录每个版本对应的栈顶。回退即可。

接下来我们将讲解可持久化栈的例题。

例题

[ABC273E] Notebook

Description

有一个版本保存系统,共有 \(10^9\) 个版本,每个版本初始都为空列表,还需要维护一个列表(后称为“当前列表”)。
您需要实现如下四种操作:

  • ADD x:在当前列表的末尾添加 \(x\)
  • DELETE:如果当前列表非空,把当前列表的末尾最后一个数删除。否则,什么也不做。
  • SAVE x:把当前列表保存至第 \(x\) 版本(在此后完成的操作不会在第 \(x\) 版本中出现,而且保存后当前列表不清空)
  • LOAD x:把当前列表变成第 \(x\) 版本(直接赋值,而不是添加,而且保存后第 \(x\) 版本不清空)
    给定 \(q\) 次操作,每次操作是以上四种操作,求每次操作的当前列表的末尾最后一个数(若数组为空输出 \(-1\))。

可持久化栈的板子题。

对于 ADD 操作, 我们需要在添加同时,新开版本并记录当前版本的栈顶,同时将当前版本节点同上一个版本节点相连。这很简单,只需要开一个变量 last 记录上一个版本号即可。

对于 DELETE 操作,直接将当前所在版本回滚到它的前驱即可。

对于 SAVE 操作,保存版本即可。

对于 LOAD 操作,也就是回滚版本。由于我们先前已经记录了每个版本所对应的栈顶,直接回滚即可。

Code
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5+5;
int n;
int q;
int idx = 0;
int fa[N],val[N];
map <int,int> pos;
int last = 0;
int main()
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>q;for(int i=1;i<=q;i++){string op;cin>>op;int x;if(op == "ADD"){cin>>x;idx ++;val[idx] = x;fa[idx] = last;last = idx; }else if(op == "SAVE") {cin>>x;pos[x] = last;}else if(op == "DELETE"){last = fa[last];}else{cin>>x;last = pos[x];}if(last) cout<<val[last]<<" ";else cout<<"-1"<<" "; }
}

练习:Luogu P6182,和本题基本一致。都是可持久化栈的板子。

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

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

相关文章

Windows Terminal 自定义 SSH 连接

我们在远程操作Linux主机时常常会使用各种Remote SSH工具,比如最常用的X Shell、MobaXterm。这些工具功能强大,但很多时候只是需要开个终端,Windows 10开始自带的Windows Terminal就不错。 Windows Terminal 是Window 10 以上系统自带的工具,对选项卡、富文本等功能支持不错…

OOP第四次blog

本次blog是本学期的最后一次blog,接下来分析最后一次小结内容的PTA作业。 本次作业分为以下部分: (1)总结三次题目集的知识点、题量、难度等情况。 (2)设计与分析:重点对题目的提交源码进行分析。 (3)采坑心得:对源码的提交过程中出现的问题及心得进行总结。 (4)改…

南昌航空大学第二次blog

本次blog是本学期的最后一次blog,接下来分析最后一次小结内容的PTA作业。 本次作业分为以下部分: (1)总结三次题目集的知识点、题量、难度等情况。 (2)设计与分析:重点对题目的提交源码进行分析。 (3)采坑心得:对源码的提交过程中出现的问题及心得进行总结。 (4)改…

(交换使逆序对数为1+并查集)CF1768D Lucky Permutation

题意:思路: 先从排好序的数组考虑:1,2,3,4,5,...n,如果交换相邻元素,必然使得逆序对数+1。 考虑先将乱序数组变成顺序数组,最后交换任意一对相邻元素即可。 将所有的i与\(p_{i}\)连边,最后形成若干个环,交换次数其实就是边数,也即点数-环数。并查集维护。 注意特殊情…

[C++ Primer] 开始

C++ Primer 第5版中英版电子版pdf开始 C++ Primer 第5版pdf中英版 夸克云盘 百度云盘 提取码:qrjn该系列记录了我在学习C++过程中经常会遗忘和混淆的相关操作语法,以备将来用到时方便查找。 加油吧!!!🙆

【MX-S1】梦熊周赛 提高组 1(同步赛)

【MX-S1】梦熊周赛 提高组 1(同步赛)\(T1\) luogu P10672 【MX-S1-T1】壁垒 \(100pts\)一个简单的结论:随着前缀长度的增长,出现的数字种类数每次只能增加 \(0\) 或 \(2\)。考虑构造时可以从这里下手。一种构造方案是这样的:优先让数字种类数增加 \(2\),即先将原先没有出…

vue学习笔记-2

1.模板语法 文本插值 <template><p>{{ msg }}</p><br/> <p>{{ num+1 }}</p><br/> <p>{{ ok?"yes":"no" }}</p> </template> <script> export default{data(){return{msg:"模板语…

Nginx 站点配置多目录管理

运维需求 在使用Nginx 对多个站点进行配置和运行维护时,如果将多个站点的配置都放在同一配置文件中,对于server 部分的调整,随着时间的推移,可能对应的配置变更是由不同的人员接手,不方便系统的部署和迁移。解决方案 为了解决这个问题,可以考虑使用include 块。用于指定加…

PNAS | 中国农大汪海团队实现转录调控序列的人工智能设计

近日,中国农业大学农学院汪海团队联合美国康奈尔大学、丹麦奥胡斯大学、北京大学现代农业研究院、坦桑尼亚农业科学院等单位在_PNAS在线发表了题为Modeling 0.6 million genes for the rational design of functional cis-regulatory variants and de novo design of cis-regu…

[C++ Primer] 关联容器

C++关联容器相关操作关联容器标准库提供了8个关联容器。类型map和multimap定义在头文件map中;set和multiset定义在头文件set中;无序容器则定义在头文件unordered_map和unordered_set中。pair标准库类型,定义在头文件utility中。关联容器额外的类型别名:关联容器insert操作:…

Kali 关闭自动锁屏功能

Kali 关闭自动锁屏功能 1、点击 [开始] -> [设置] -> [电源管理器]2、选择 [安全性],将 [自动锁定会话] 选为 [从不],将 [当系统休眠时锁定屏幕] 取消勾选,点击 [关闭]

键盘记录大师:用pynput轻松捕获每一个按键,包括组合键和功能键

哈喽,大家好,我是木头左!揭秘键盘输入的监控神器 - pynput库 在数字时代,键盘是与计算机交流的主要工具。无论是编写代码、撰写文档还是进行日常通讯,键盘的每一次敲击都承载着信息。而在某些场景下,可能需要记录这些信息,比如开发一个学习打字的软件、监控儿童的上网行…

word通用模板说明

个人偷懒,标题、表、图、公式按章节自动编号,字体与间距按照武汉理工大学硕士论文设置,方便平时报告用,模板在个人文件夹中https://files.cnblogs.com/files/blogs/806514/%E9%80%9A%E7%94%A8word%E6%A8%A1%E6%9D%BF.zip?t=1719659030&download=true 标题自动编号 点击…

HydroOJ 从入门到入土(20)已通过的题目显示 AC 代码

定期的代码汇总分析和整理是必要的。个人面板里,通过的题目,直接链接到对应的AC记录。用处就是可以按人汇总,便于学生自己整理,以及老师分析学生。 权限:看不了别人代码的人,依然看不了别人代码。 效果修改后端 进入 user.ts 文件 435 行左右: cd /usr/local/share/.con…

模拟集成电路设计系列博客——8.2.2 LC振荡器

8.2.2 LC振荡器 LC振荡器是调谐振荡器的一个例子。环形振荡器使用有源放大器级来提供环路不稳定性所需要的180相移,调谐振荡器向反馈环路中插入调谐(谐振)电路来提供相移。在LC振荡器的例子中,谐振是由一个并联的LC电路实现的。 一个简单的LC振荡器如下图(a)所示,其小信号…

安装编译ffmpeg

原文链接 安装MSYS2msys2是一款跨平台编译套件,它模拟linux编译环境,支持整合mingw32和mingw64,能很方便的在windows上对一些开源的linux工程进行编译运行。类似的跨平台编译套件有:msys,cygwin,mingw 优势: 相对于 cygwin 和 msys 等环境,它支持 pacman 包管理器,这…

LLM并行训练4-megascale论文学习

字节megascale论文学习笔记算法优化 并行注意力机制 \[串行版本: y = x + MLP(LayerNorm(x + Attention(LayerNorm(x)))) \]\[并行版本: y = x + MLP(LayerNorm(x)) + Attention(LayerNorm(x)))) \]乍一看确实不是等价的, attention那块的后置mlp去哪了..这个其实没有理论证明,…

【Linux系列】centos搭建本地源

开始备份:查看光盘挂载路径:❗转义符关闭防火墙:测试一下:🎉Congratulations on successfully switching your local source!