【主席树】P3919 【模板】可持久化线段树 1

P3919 【模板】可持久化线段树 1(可持久化数组) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

template<class Node>
struct PersidentSegmentTree {
#define lc(u) tr[u].l
#define rc(u) tr[u].r
#define val(u) tr[u].v
	const int n;
	int tot = 0;
	vector<Node> tr;
	vector<int> root;

	PersidentSegmentTree(): n(0) {}

	PersidentSegmentTree(int n_): n(n_) {
		int N = (n << 5) + 10;
		tr.reserve(N); root.reserve(N);
		tr.resize(N); root.resize(N);
	}

	PersidentSegmentTree(vector<int>& a): PersidentSegmentTree(a.size() - 1) {
		function<void(int&, int, int)> build = [&](int& now, int l, int r) {
			now = ++ tot;
			if (l == r) {
				val(now) = a[l];
				return ;
			}
			int m = (l + r) >> 1;
			build(lc(now), l, m);
			build(rc(now), m + 1, r);
		};
		build(root[0], 1, n);
	}

	//last代表前缀,now代表新树根
	void insert(int& now, int last, int l, int r, int pos, int w) {
		now = ++ tot;
		tr[now] = tr[last];
		if (l == r) {
			val(now) = w;
			return;
		}
		int m = l + r >> 1;
		if (pos <= m)
			insert(lc(now), lc(last), l, m, pos, w);
		else
			insert(rc(now), rc(last), m + 1, r, pos, w);
	}

	//单点
	int query(int now, int l, int r, int pos) {
		if (l == r) {
			return val(now);
		}

		int m = l + r >> 1;
		if (pos <= m)
			return query(lc(now), l, m, pos);
		else
			return query(rc(now), m + 1, r, pos);
	}

	//区间查询 [u,v]->[root[l-1],root[r]]
	int query(int u, int v, int l, int r, int pos) {
		if (l == r) {
			return val(v);
		}

		int m = l + r >> 1;
		if (pos <= m)
			return query(lc(u), lc(v), l, m, pos);
		else
			return query(rc(u), rc(v), m + 1, r, pos);
	}
};

struct Node {
	int l, r, v;
};

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int n, q;
	cin >> n >> q;

	vector<int> a(n + 1);
	for (int i = 1; i <= n; i ++)
		cin >> a[i];

	PersidentSegmentTree<Node> pst(a);

	for (int i = 1; i <= q; i ++) {
		int v, op, pos;
		cin >> v >> op >> pos;
		if (op == 1) {
			int val;
			cin >> val;
			pst.insert(pst.root[i], pst.root[v], 1, n, pos, val);//新建版本
		} else {
			cout << pst.query(pst.root[v], 1, n, pos) << '\n';
			pst.root[i] = pst.root[v];//保存当前版本
		}
	}

	return 0;
}
posted @ 2024-08-08 00:27  Ke_scholar  阅读(3)  评论(0编辑  收藏  举报