社区讨论

已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 条回复,欢迎继续交流。

正在加载回复...