题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3038
题意
给出m个区间,范围为1到n,每给出一个区间要求判断是否与前面的区间矛盾如果矛盾则不处理,最终输出矛盾区间的个数。
范围:1<=n<=2e5 1<=m<=40000
思路:带权并查集
考虑区间的几种状态:1.区间相离 2.区间相交 3. 区间内含 4.区间相切
- 区间相离:不会出现矛盾,直接进行区间合并
- 区间相交:通过调整,还是能满足每个区间和为某个值
- 区间内含:两个区间不会相互影响,直接合并即可
- 区间相切:相切的话,能合并则合并,如果已经存在共同根节点,则查询是否矛盾
因为要考虑前一个区间与这个区间的关系所以左端点需要-1,在查找的时候对该点到根节点的距离进行更新。
如图输入左端点为x,右端点为y,x->y为z,sum为当前点到根节点的距离,则合并之后
#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;
}