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;
}