How Many Answers Are Wrong HDU - 3038 带权并查集

题解

题目大意,给你若干个区间和,问和之前所说相悖的有多少个,注意多组样例输入

使用带权并查集求解,将区间x, y转化为[x, y)的左闭右开区间方便处理
f[i]表示i的父节点是谁,要求父节点大于等于子节点,r[i]表示[i, f[i])区间和为多少,初始化时自身父节点为自身,自然[i, i)为0
令f[i]表示i的父节点是谁,r[i]表示区间[i, f[i])的和为多少

压缩路径时直接加上父节点到祖父节点的和,即[x, fx) + [fx, ffx) = [x, ffx),fx表示x的父节点ffx表示x的祖父节点
合并集合时将fx接在fy后面,利用关系传递性fx->fy=fx->x->y->fy,需要注意fx和fy大小关系(好像不判断为负也不影响答案 )

AC代码

#include <stdio.h>
#include <bits/stdc++.h>
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int MAXN = 2e5 + 10;
int f[MAXN], r[MAXN]; //f[i]表示i的父节点 要求父节点大于等于子节点 r[i]表示区间[i, f[i])的和

int find(int x) //查询x的根节点是谁
{
	if (f[x] != x)
	{
		int fx = f[x]; //记录原父节点
		f[x] = find(f[x]); //压缩路径
		r[x] = r[x] + r[fx]; //[x, fx) + [fx, ffx) = [x, ffx)
	}
	return f[x];
}
void join(int x, int y, int z) //设置x与y的[x, y)区间和为z
{
	int fx = find(x), fy = find(y); //得到xy的父节点并压缩至直连根节点
	if (fx != fy) //不是同一个父节点
	{
		if (fx > fy) //保证父节点大于等于子节点
			swap(fx, fy), swap(x, y), z = -z; //全部翻转
		f[fx] = fy; //把fx接在fy上
		r[fx] = -r[x] + z + r[y]; //传递fx->x->y->fy
	}
}
int query(int x, int y) //查询[x, y)的和 不能确定为-1
{
	if (find(x) == find(y)) //同一个根节点才能确定
		return r[x] - r[y]; //[x, f) - [y, f) = [x, y)
	return -1;
}
int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int n, m;
	while (scanf("%d%d", &n, &m) != EOF)
	{
		for (int i = 1; i <= n + 1; i++)
			f[i] = i, r[i] = 0; //初始自身为自身父节点 [i, i)为0
		int ans = 0;
		while (m--)
		{
			int x, y, z;
			scanf("%d%d%d", &x, &y, &z);
			y++; //转换为[x, y+1)
			int k = query(x, y);
			if (k == -1) //无法推断
				join(x, y, z);
			else if (z != k) //和已有信息不同
				ans++;
		}
		cout << ans << endl;
	}

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值