1525 重组公司

51nod 1525 重组公司


codeforces  562D 566D Restructuring Company


两个并查集。

一个并查集用于维护 部门合并
另一个用于维护第二种操作的线段合并。   线段附加一个属性,为该线段最右端的位置。

两个并查集均能采用 按秩优化 与路径压缩。

从而复杂度为 接近线性。 O((n+q)(alpha(n)));

#include <cstdio>

#define maxsize 200002
int myrank0[maxsize], father0[maxsize], father1[maxsize], mynext[maxsize], myrank1[maxsize];
int n, q;


inline int LINK0(int id1, int id2)
{
	int rank1, rank2;
	if ((rank1 = myrank0[id1]) > (rank2 = myrank0[id2]))
	{
		return father0[id2] = id1;
	}
	else
	{
		if (rank1 == rank2)
		{
			++myrank0[id2];
		}
		return father0[id1] = id2;
	}
}

inline int LINK1(int id1, int id2)
{
	int rank1, rank2;
	if ((rank1 = myrank1[id1]) > (rank2 = myrank1[id2]))
	{
		return father1[id2] = id1;
	}
	else
	{
		if (rank1 == rank2)
		{
			++myrank1[id2];
		}
		return father1[id1] = id2;
	}
}
inline int findfather0(int index)
{
	if (index != father0[index])
	{
		father0[index] = findfather0(father0[index]);
	}
	return father0[index];
}

inline int findfather1(int index)
{
	if (index != father1[index])
	{
		father1[index] = findfather1(father1[index]);
	}
	return father1[index];
}

inline void UNION0(int id1, int id2)
{
	LINK0(findfather0(id1), findfather0(id2));
}

inline void UNION1(int id1, int id2)
{
	LINK1(findfather1(id1), findfather1(id2));
}

void init()
{
	for (int i = 1; i <= n; ++i)
	{
		mynext[i] = (father0[i] = father1[i] = i) + 1;
	}
}

void getInput()
{
	scanf("%d%d", &n, &q);
	init();
	int flag, x, y, x1, x2;
	for (int i = 0; i < q; ++i)
	{
		scanf("%d%d%d", &flag, &x, &y);
		if (1 == flag)
		{
			UNION0(x, y);
		}
		else if (2 == flag)
		{
			++y;

			x1 = mynext[findfather1(x)];
			while (x1 < y)
			{
				UNION0(x, x1);
				x2 = mynext[findfather1(x1)];
				UNION1(father1[x], father1[x1]);
				x = x1;
				x1 = x2;
			}
			mynext[findfather1(father1[x])] = x1;

		}
		else
		{
			if (findfather0(x) == findfather0(y))
			{
				printf("YES\n");
			}
			else
			{
				printf("NO\n");
			}
		}

	}
}

int main()
{
	getInput();
	return 0;
}

复杂度分析:


第一种:复杂度就是正常的并查集复杂度。

第二种: 对于x-y进行合并。 注意到,每次进行第二种查询时,都至少有一个findfather操作,后面再紧跟着ki个 区间合并与findfather操作。而每进行一次,区间数就少1。总区间数只有n。因此q次查询至多进行q+n次findfather操作与n次区间合并操作。

因此总复杂度仍然是 并差集 的复杂度,几乎线性。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值