请教一下为什么可持久化并查集不能用路径压缩
查看原帖
请教一下为什么可持久化并查集不能用路径压缩
554746
yiming564楼主2024/2/24 20:57

看题解里写的都是按秩合并的方法,我想试试用路径压缩,但不知为什么死活MLE,用了各种内存优化都不行

下面贴出代码,使用可持久化二叉搜索树(毕竟不用修改,就不用平衡树了)实现的可持久化数组,并在此之上实现的可持久化并查集。使用了#pragma pack(1)关闭结构体内存对齐,优化后从40pts->92ptx,但还是因为内存问题过不去。

#include <bits/extc++.h>

#pragma pack(1)

class immutable_array_t
{
public:
	struct node_t
	{
		int key;
		int value;
		node_t *left, *right;
		uint16_t mark;
	};

	node_t *bp, *sp, **root;
	int active;
	
	immutable_array_t(size_t pool_size, size_t version_size)
	{
		bp = (node_t *)malloc(sizeof(node_t) * pool_size);
		sp = bp;
		root = (node_t **)malloc(sizeof(node_t *) * version_size);
	}
	~immutable_array_t()
	{
		free(bp);
		free(root);
	}
	node_t *build_tree(int l, int r)
	{
		if (l > r)
			return NULL;
		int mid = (l + r) >> 1;
		node_t *node = bp + mid;
		node->key = mid;
		node->left = build_tree(l, mid - 1);
		node->right = build_tree(mid + 1, r);
		return node;
	}
	__always_inline void init(int max)
	{
		root[0] = build_tree(0, max - 1);
		sp += max;
	}

	__always_inline void safe_update_mark(node_t *node)
	{
		if (node != NULL)
			node->mark++;
	}

	__always_inline void copy_root(int origin)
	{
		active++;
		root[active] = sp++;
		*root[active] = *root[origin];
		safe_update_mark(root[active]->left);
		safe_update_mark(root[active]->right);
		root[active]->mark = 0;
	}

	// __always_inline int &simple_at(int key)
	// {
	// 	auto it = root[active];
	// 	while (it != NULL)
	// 	{
	// 		if (key < it->key)
	// 			it = it->left;
	// 		else if (key > it->key)
	// 			it = it->right;
	// 		else
	// 			return it->value;
	// 	}
	// 	assert(false);
	// }

	node_t *path_copy(node_t *it, int key, node_t *&target)
	{
		if (it->mark != 0)
		{
			*sp = *it;
			it->mark--;
			sp->mark = 0;
			it = sp++;
			safe_update_mark(it->left);
			safe_update_mark(it->right);
		}
		if (key < it->key)
			it->left = path_copy(it->left, key, target);
		else if (key > it->key)
			it->right = path_copy(it->right, key, target);
		else
			target = it;
		return it;
	}

	int find(int key)
	{
		node_t *target;
		path_copy(root[active], key, target);
		if (target->value != key)
			target->value = find(target->value);
		return target->value;
	}

	__always_inline void merge(int root_x, int root_y)
	{
		node_t *target;
		path_copy(root[active], root_x, target);
		target->value = root_y;
	}
	// __always_inline node_t *find(int key, int origin_version, int new_version)
	// {
	// 	root[new_version] = sp++;
	// 	*root[new_version] = *root[origin_version];
	// 	auto it = root[new_version];
	// 	while (it != NULL)
	// 	{
	// 		if (key < it->key)
	// 			it = it->left;
	// 		else if (key > it->key)
	// 			it = it->right;
	// 		else
	// 			return it;
	// 	}
	// 	return NULL;
	// }
};

immutable_array_t forest(5000000, 200001);
int n, m;
int op, a, b;

int main()
{
	// freopen64("P3402_11.in", "r", stdin);
	scanf("%d %d", &n, &m);
	for (int i = 0; i < n; i++)
		forest.bp[i].value = i;
	forest.init(n);
	for (int i = 0; i < m; i++)
	{
		scanf("%d", &op);
		if (op == 1)
		{
			scanf("%d %d", &a, &b);
			a--;
			b--;
			forest.copy_root(i);
			forest.merge(forest.find(a), forest.find(b));
		}
		else if (op == 2)
		{
			scanf("%d", &op);
			forest.copy_root(op);
		}
		else
		{
			scanf("%d %d", &a, &b);
			a--;
			b--;
			forest.copy_root(i);
			printf(forest.find(a) == forest.find(b) ? "1\n" : "0\n");
		}
	}
	return 0;
}

求助!!!各位大佬能否解释一下为什么不能路径压缩,或者给出优化内存的方法。我分析我的空间复杂度应该给是 O(n+mlgn)O(n+mlgn),不应该啊

2024/2/24 20:57
加载中...