【Luogu P3834】可持久化数组(可持久化线段树)
题目链接
可持久化线段树模板题。
这里总结一下可持久化线段树。
可持久化数据结构就是能恢复历史状态的数据结构,比如可持久化\(Trie\),并查集,平衡树。
可持久化数组是最基础的,这里通过可持久化线段树来实现。
可持久化线段树
·复杂度:时间\(O(n\log n)\),空间\(O(m\log n)\)。
·实现:
这里只针对单点修改的可持久化,区间修改是很复杂的。
可以发现,线段树的每次单点修改只会改变树上的\(\log n\)个节点,于是我们对这\(\log n\)个节点创建副本,如图(自绘丑)
红点是我们要修改的点,红边经过的点都是值会发生变化的,我们对其建立副本,如图:
可以看到,每个被修改的点一个副本,和没被修改的点正常连边,这样每次操作只会增加\(\log n\)个节点。
然后我们每次修改把修改后的副本的根记录下来,如图:
然后从这个根遍历树,就是我们要的历史版本了。
代码实现:
#include <cstdio>
#define re register
inline int read(){
s = 0, w = 1;
char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') w = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar(); }
return s * w;
}
const int MAXN = 1000010;
const int MAXM = 1000010;
struct SegTree{
int lc, rc, val;
SegTree(){ lc = rc = val = 0; }
}t[MAXM * 20];
int tot, a[MAXN], root[MAXN];
int build(int l, int r){
int id = ++tot;
if(l == r){ t[id].val = a[l]; return id; }
int mid = (l + r) >> 1;
t[id].lc = build(l, mid);
t[id].rc = build(mid + 1, r);
return id;
}
int insert(int now, int l, int r, int x, int p){
int id = ++tot; //创立副本
t[id] = t[now]; //先与原点保持一致
if(l == r){ t[id].val = p; return id; } //修改副本(不改原点)
int mid = (l + r) >> 1;
if(x <= mid) t[id].lc = insert(t[now].lc, l, mid, x, p); //只把改变的儿子变为副本,另一个儿子仍是原来的
else t[id].rc = insert(t[now].rc, mid + 1, r, x, p);
return id; //返回副本编号
}
int ask(int now, int l, int r, int x){ //查询和普通线段树没有区别
if(l == r) return t[now].val;
int mid = (l + r) >> 1;
if(x <= mid) return ask(t[now].lc, l, mid, x);
else return ask(t[now].rc, mid + 1, r, x);
}
int n, m;
int v, opt;
int A, B;
int main(){
n = read(); m = read();
for(int i = 1; i <= n; ++i)
a[i] = read();
root[0] = build(1, n); //初始版本
for(int i = 1; i <= m; ++i){
v = read(); opt = read();
if(opt == 1){
A = read(); B = read();
root[i] = insert(root[v], 1, n, A, B); //在版本v的基础上把位置A上的数变为B
}
else{
A = read();
printf("%d\n", ask(root[v], 1, n, A));
root[i] = root[v];
}
}
return 0;
}
【Luogu P3834】可持久化数组(可持久化线段树)的更多相关文章
- luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树)(主席树)
luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目 #include<iostream> #include<cstdlib> #include< ...
- Luogu 3373 又乘又加的线段树
Luogu 3373 又乘又加的线段树 当给一个节点加上一个加法标记时,直接把加法标记 += 新值: 当给一个节点加上一个乘法标记时,把乘法标记和加法标记同时 *= 新值.(注意pushdown函数中 ...
- Luogu P3919 【模板】可持久化数组 可持久化线段树
其实就是可持久化线段树的模板题线段树不会看这里 #include<bits/stdc++.h> ; using namespace std; ]; ],rc[N*],val[N*],cnt ...
- luogu P3834 【模板】可持久化线段树 1(主席树) 查询区间 [l, r] 内的第 k 小/大值
————————————————版权声明:本文为CSDN博主「ModestCoder_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明.原文链接:https:// ...
- P3919 【模板】可持久化数组 -初步探究主席树
本篇blog主要是给自己(大家)看的. 感谢longlongzhu123奆佬(此人初二LCT)的指点,使本蒟蒻可以快速开始主席树入门. what is 主席树? $ $主席树这个名字只不 ...
- Luogu 45887 全村最好的嘤嘤刀(线段树 树状数组)
https://www.luogu.org/problemnew/show/T45887 题目背景 重阳节到了,我们最好的八重樱拥有全村最好的嘤嘤刀…… 题目描述 在绯玉丸力量的影响下,八重村成了一条 ...
- BZOJ 3489 A simple rmq problem 可持久化KDtree/二维线段树
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3489 题意概述: 给出一个序列,每次询问一个序列区间中仅出现了一次的数字最大是多少,如果 ...
- HDU 1166 敌兵布阵 (数状数组,或线段树)
题意:... 析:可以直接用数状数组进行模拟,也可以用线段树. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000&quo ...
- 【BZOJ3110】【整体二分+树状数组区间修改/线段树】K大数查询
Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位 ...
- BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 418 Solved: 235 [ Submit][ ...
随机推荐
- Linux使用imagemagick的convert命令压缩图片,节省服务器空间
1,安装imagemagick yum install ImageMagick 2,获取图片 find ./ -regex '.*\(jpg\|JPG\|png\|jpeg\)' -size +500 ...
- sqlserver一次性删除master数据库中的所有用户添加的表
use master; go sp_msforeachtable @command1="drop table ?" go
- 【APUE】Chapter4 File and Directories
4.1 Introduction unix的文件.目录都被当成文件来看待(vi也可以编辑目录):我猜这样把一起内容都当成文件的原因是便于统一管理权限这类的内容 4.2 stat, fstat, fst ...
- 2.Linux文件和目录
1. 目录和路径 linux下比较特殊的目录: . 代表此层目录 .. 代表上一层目录 - 代表前一个工作目录 ~ 代表『目前使用者身份』所在的home目录 ~account 代表 account 这 ...
- 虚拟现实-VR-UE4-编译源代码后,无法运行
情况是这个样,在一开始我编译后,是可以运行,但是当我重新做系统后,再次运行时,每次都是到加载的18%的时候提示了如下错误 具体解决方法还没有找到,正在努力找中.........,会后续更新 同时希望有 ...
- Swiper 常用功能及配置清单
内容来源于Swiper中文在线(http://www.swiper.com.cn/),由于Swiper功能强大,这里只将常用的功能列出来,方便开发. 这里统一使用Swiper最新版 4.0做为演示! ...
- Gym101981I Magic Potion(最大流)
Problem I. Magic Potion There are n heroes and m monsters living in an island. The monsters became v ...
- 解决Linux下启动Tomcat遇到Neither the JAVA_HOME ...报错
解决Linux下启动Tomcat遇到Neither the JAVA_HOME ...报错 Neither the JAVA_HOME nor the JRE_HOME environment var ...
- Linux 项目实用命令
总结一下Linux下常用的命令 nc nc命令,这是Linux一般都带有的,被誉为“瑞士军刀”.windows和Linux都有,可以下载安装对应的平台工具.使用UDP和TCP协议的网络连接去读写数据, ...
- Delphi 之 编辑框控件(TEdit)
TEdit 组件主要用于数据的输入和显示和编辑等操作. AutoSelect 获取组件焦点.该属性只能在单行文本组件使用.值为True为选中.false则不选中. BorderStyle 设置编辑框控 ...