【模板】可持久化数组

可持久化数组


可持久化数组也是基于主席树,不过要比可持久化线段树写起来简单些,且只有叶节点维护值。

建树

这里的建树与主席树类似。

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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值