HDU3038 带权并查集

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3038

题意

  给出m个区间,范围为1到n,每给出一个区间要求判断是否与前面的区间矛盾如果矛盾则不处理,最终输出矛盾区间的个数。
范围:1<=n<=2e5 1<=m<=40000

思路:带权并查集

  考虑区间的几种状态:1.区间相离 2.区间相交 3. 区间内含 4.区间相切

  1. 区间相离:不会出现矛盾,直接进行区间合并
  2. 区间相交:通过调整,还是能满足每个区间和为某个值
  3. 区间内含:两个区间不会相互影响,直接合并即可
  4. 区间相切:相切的话,能合并则合并,如果已经存在共同根节点,则查询是否矛盾
    因为要考虑前一个区间与这个区间的关系所以左端点需要-1,在查找的时候对该点到根节点的距离进行更新。
    在这里插入图片描述
    如图输入左端点为x,右端点为y,x->y为z,sum为当前点到根节点的距离,则合并之后
sum[r2]=z-sum[y]+sum[x]
(需要注意方向)
#include<bits/stdc++.h>
using namespace std;
#define maxn 200005
#define ll long long
#define inf 1000000000000000009
#define IOS ios::sync_with_stdio(false)

int ff[maxn],sum[maxn];
int find(int x)
{
    if(ff[x]==x)
        return x;
    int t=ff[x];
    ff[x]=find(ff[x]);
    sum[x]+=sum[t];
    return ff[x];
}

int main()
{
    IOS;
    int n,m;
    while(cin>>n>>m)
    {
        for(int i=0; i<=n; i++)
            ff[i]=i,sum[i]=0;
        int ans=0;
        for(int i=0; i<m; i++)
        {
            int x,y,z;
            cin>>x>>y>>z;
            x--;//区间为左开右闭
            int nx=find(x),ny=find(y);
            if(nx==ny)
            {
                if(sum[y]-sum[x]!=z)ans++;
            }
            else
            {
                ff[ny]=nx;
                sum[ny]=z-sum[y]+sum[x];
            }
        }
        cout<<ans<<"\n";
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值