【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][ ...
随机推荐
- Page Object 设计模式介绍
Page Object 是 Selenium 自动化测试项目开发实践的最佳设计模式之一,Page Object 的主要体现于对界面交互细节的封装,这样可以使测试案例更关注与业务而非界面细节,提高测试案 ...
- Mysql性能优化四:分库,分区,分表,你们如何做?
分库分区分表概念 分区 就是把一张表的数据分成N个区块,在逻辑上看最终只是一张表,但底层是由N个物理区块组成的 分表 就是把一张数据量很大的表按一定的规则分解成N个具有独立存储空间的实体表.系统读写时 ...
- P4332三叉神经树
题面 \(Solution\) 通过模拟,我们会发现每次修改 \(x\),只会改变从 \(x\) 向上一段连续的链的输出. 例如将 \(x\) 点从 \(0\) 改为 \(1,\) 那么它会影响从它向 ...
- ubuntu中 VI 方向键、删除键问题
这两天重新装的ubuntu系统,发觉使用VI时,方向键按下去后变成ABCD,删除键无效.网上搜寻一番,应该是VI软件本身的问题,顾卸载重装即可,步骤如下: 1.执行命令 sudo apt-get re ...
- 容器基础(七): 使用docker compose部署程序
配置 在上一节的基础上, 增加如下的docker-compose.yml文件, 然后用docker-compose up命令启动容器进行部署: version: " services: s ...
- mysql insert into select 语法
Insert into Table2(field1,field2,...) select value1,value2,... from Table1 这样就对了
- AM5728通过GPMC接口与FPGA高速数据通信实现
硬件:AM5728开发板:Artix-7开发板软件:Linux am57xx-evm 4.4.19:Vivado 2015.2作者:杭州矢志信息科技有限公司邮箱:admin@sysjoint.com ...
- Daily Scrum02 12.04
第二轮迭代已经进行到了白热化阶段,大家在被编译搞的水深火热的同时依然没有忘记我们的具有颠覆性的团队项目.虽然第一轮迭代我们的成绩不错,但是一定要克服时间不充裕,任务互相冲突的困难,克服不可避免的舆论压 ...
- [转]Linux UDP严重丢包问题的解决
测试系统在Linux上的性能发现丢包率极为严重,发210000条数据,丢包达110000之巨,丢包率超过50%.同等情形下Windows上测试,仅丢几条数据.形势严峻,必须解决.考虑可能是因为协议栈B ...
- Spring Boot学习(二):配置文件
目录 前言 方式1:通过配置绑定对象的方式 方式2:@Value("${blog.author}")的形式获取属性值 相关说明 注解@Value的说明 参考 前言 Spring B ...