题目链接

可持久化线段树模板题。

这里总结一下可持久化线段树。

可持久化数据结构就是能恢复历史状态的数据结构,比如可持久化\(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】可持久化数组(可持久化线段树)的更多相关文章

  1. luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树)(主席树)

    luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目 #include<iostream> #include<cstdlib> #include< ...

  2. Luogu 3373 又乘又加的线段树

    Luogu 3373 又乘又加的线段树 当给一个节点加上一个加法标记时,直接把加法标记 += 新值: 当给一个节点加上一个乘法标记时,把乘法标记和加法标记同时 *= 新值.(注意pushdown函数中 ...

  3. Luogu P3919 【模板】可持久化数组 可持久化线段树

    其实就是可持久化线段树的模板题线段树不会看这里 #include<bits/stdc++.h> ; using namespace std; ]; ],rc[N*],val[N*],cnt ...

  4. luogu P3834 【模板】可持久化线段树 1(主席树) 查询区间 [l, r] 内的第 k 小/大值

    ————————————————版权声明:本文为CSDN博主「ModestCoder_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明.原文链接:https:// ...

  5. P3919 【模板】可持久化数组 -初步探究主席树

    本篇blog主要是给自己(大家)看的. 感谢longlongzhu123奆佬(此人初二LCT)的指点,使本蒟蒻可以快速开始主席树入门. what is 主席树? $        $主席树这个名字只不 ...

  6. Luogu 45887 全村最好的嘤嘤刀(线段树 树状数组)

    https://www.luogu.org/problemnew/show/T45887 题目背景 重阳节到了,我们最好的八重樱拥有全村最好的嘤嘤刀…… 题目描述 在绯玉丸力量的影响下,八重村成了一条 ...

  7. BZOJ 3489 A simple rmq problem 可持久化KDtree/二维线段树

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3489 题意概述: 给出一个序列,每次询问一个序列区间中仅出现了一次的数字最大是多少,如果 ...

  8. HDU 1166 敌兵布阵 (数状数组,或线段树)

    题意:... 析:可以直接用数状数组进行模拟,也可以用线段树. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000&quo ...

  9. 【BZOJ3110】【整体二分+树状数组区间修改/线段树】K大数查询

    Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位 ...

  10. BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec   Memory Limit: 512 MB Submit: 418   Solved: 235 [ Submit][ ...

随机推荐

  1. Python简要标准库(5)

    hashlib Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等. 基本的生成MD密匙的函数 import hashlib md5 = hashlib.md5() md5.up ...

  2. 【Linux运维】Centos7上借助ansible搭建LVS+Keepalived

    安装ansible 安装ansible: [root@localhost ~]# /etc/hosts 192.168.19.129 web129.yanglt.com web129 192.168. ...

  3. 成为IT精英,我奋斗7年【转】

    这些日子 我一直在写一个实时操作系统内核,已有小成了,等写完我会全部公开,希望能够为国内IT的发展尽自己一份微薄的力量.最近看到很多学生朋友和我当年一样没 有方向 ,所以把我的经历写出来与大家共勉,希 ...

  4. DFS(7)——poj1011Sticks

    一.题目回顾 题目链接:Sticks 题意:给出一定数量的小木棒的长度,它是由等长的若干木棒随意砍断所得到的.对于给定的一组小木棒,请求出原始木棒的最小长度. 二.解题思路 DFS+剪枝 本题剪枝不到 ...

  5. Android隐藏键盘

    今天接到的任务是在验证码输入框中加入键盘监听事件,需要点击Enter实现登录,这个比较好实现,但是在登录时,键盘并没有隐藏掉,看上去很别扭,因此,百度了一堆方法,但是都无济于事,最后找到了一个,如下, ...

  6. windows下 eclipse搭建spark java编译环境

    环境: win10 jdk1.8 之前有在虚拟机或者集群上安装spark安装包的,解压到你想要放spark的本地目录下,比如我的目录就是D:\Hadoop\spark-1.6.0-bin-hadoop ...

  7. 关于debian配置的问题汇总

    debian的apache多域名配置: https://www.digitalocean.com/community/tutorials/how-to-set-up-apache-virtual-ho ...

  8. gdb调试行号错位

    http://blog.csdn.net/wangxmin2005/article/details/8128192 gdb调试过程中出现行号错位的情况,原因一般有两个: 1. 编译器的优化可能把某些语 ...

  9. CFS 调度器

    CFS调度器的原理明白了但是有个地方,搜遍了整个网络也没找到一个合理的解释: if (delta > ideal_runtime) resched_task(rq_of(cfs_rq)-> ...

  10. [剑指Offer] 38.二叉树的深度

    题目描述 输入一棵二叉树,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度. [思路1]递归 /* struct TreeNode { int v ...