可持久化数组
可持久化数组也是基于主席树,不过要比可持久化线段树写起来简单些,且只有叶节点维护值。
建树
这里的建树与主席树类似。
int Build(int l, int r) {
int k = ++tot;
if(l == r) {
tree(k) = val[l];
return k;
}
ls(k) = Build(l, mid);
rs(k) = Build(mid + 1, r);
return k;
}
修改
修改时我们只需递归寻找叶节点,并在途中新建节点以实现可持久化。
int Modify(int pre, int l, int r, int x, int v) {
int k = ++tot;
t[k] = t[pre]; //继承历史版本
if(l == r) {
tree(k) = v;
return k;
}
if(x <= mid) ls(k) = Modify(ls(pre), l, mid, x, v);
else rs(k) = Modify(rs(pre), mid + 1, r, x, v);
return k;
}
查询
只需要递归寻找到叶节点返回其值即可。
int Query(int k, int l, int r, int x) {
if(l == r) return tree(k);
if(l <= mid) return Query(ls(k), l, mid, x);
else return Query(rs(k), mid + 1, r, x);
}
#include <bits/stdc++.h>
#define maxn 1000005
using namespace std;
int rt[maxn], val[maxn];
int read() {
int ret = 0, f = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch)) {
ret = (ret << 1) + (ret << 3) + (ch ^ '0');
ch = getchar();
}
return ret * f;
}
class HJT {
private:
#define ls(k) t[k].ls
#define rs(k) t[k].rs
#define tree(k) t[k].tree
#define mid ((l + r) >> 1)
struct node {
int ls, rs, tree;
}t[maxn << 5];
int tot;
public:
int Build(int l, int r) {
int k = ++tot;
if (l == r) {
tree(k) = val[l];
return k;
}
ls(k) = Build(l, mid);
rs(k) = Build(mid + 1, r);
return k;
}
int Modify(int pre, int l, int r, int x, int v) {
int k = ++tot;
t[k] = t[pre];
if (l == r) {
tree(k) = v;
return k;
}
if (x <= mid) ls(k) = Modify(ls(pre), l, mid, x, v);
else rs(k) = Modify(rs(pre), mid + 1, r, x, v);
return k;
}
int Query(int k, int l, int r, int x) {
if (l == r) return tree(k);
if (x <= mid) return Query(ls(k), l, mid, x);
else return Query(rs(k), mid + 1, r, x);
}
}T;
int n, m;
int main() {
n = read(), m = read();
for (int i = 1; i <= n; i++)
val[i] = read();
rt[0] = T.Build(1, n);
for (int i = 1, t, opt, x, v; i <= m; i++) {
t = read(), opt = read(), x = read();
rt[i] = rt[t];
if (opt == 1) {
v = read();
rt[i] = T.Modify(rt[i], 1, n, x, v);
}
else {
cout << T.Query(rt[i], 1, n, x) << endl;
}
}
return 0;
}