社区讨论
已AC非主席树,求证明正确性
P3919【模板】可持久化线段树 1(可持久化数组)参与者 2已保存回复 1
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @miu4k13t
- 此快照首次捕获于
- 2025/12/06 18:02 2 个月前
- 此快照最后确认于
- 2025/12/08 21:10 2 个月前
因为一次只修改一个节点,直接记录操作即可(从PS来的灵感,有一个操作记录),然后回溯查找
直接回溯会导致最大的一个测试点TLE,所以进行了一点优化,用并查集优化操作链
求证明正确性,我也不知道怎么ac的
代码(ai已优化可读性):
CPP#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
struct Op {
int ver, pos, val;
};
Op ops[N]; // 记录操作,用于回溯
int n, m, a[N], fa[N]; // fa 并查集,快速回溯
int find(int tv, int pos) {
int cur = tv;
while (1) {
if (ops[cur].pos == pos) return cur;
if (cur == 0) return 0;
// 路径压缩
if (fa[cur] != cur && fa[cur] != 0) {
cur = fa[cur]; // 跳转到已缓存的答案
} else {
cur = ops[cur].ver; // 向上回溯
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i];
ops[0] = {0, 0, 0};
fa[0] = 0;
for (int i = 1; i <= m; i++) {
int v, op, p;
cin >> v >> op >> p;
if (op == 1) {
int c;
cin >> c;
ops[i] = {v, p, c};
fa[i] = i; // 直接修改
} else {
int fver = find(v, p);
int ans = (fver == 0) ? a[p] : ops[fver].val;
cout << ans << endl;
ops[i] = ops[v];
fa[i] = fver; // 记录
}
}
return 0;
}
回复
共 1 条回复,欢迎继续交流。
正在加载回复...