题意
第一行两个整数n, m; n表示数组长度,一共m组 。之后每行三个整数,a, b, v:表示数组第a个元素到b第个元素的和为v
判断输入的区间有几组是错误的。
思路
看代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=200005;
int pre[maxn];
int sum[maxn]; //表示该点到根节点的距离
int find(int x)
{
//这个代码的高明之处就在于Find过程中就将所需要的结点进行更新,并且每棵树的高度不会超过2,所以递归深度也很浅
if(x!=pre[x])
{
int t=pre[x];
//将寻找根途中碰到的所有的结点都直接接到根上,这样可以降低递归深度,
pre[x]=find(pre[x]);
sum[x]+=sum[t]; //利用递归函数的特性,更新sum数组
}
return pre[x];
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
int cnt=0;
for(int i=0;i<=n;i++) //初始化
{
pre[i]=i;
sum[i]=0;
}
for(int i=0;i<m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
a--; //两个闭区间不好处理,转化为左开右闭。半闭半开区间有一个性质,就是 (a,b]+(b,c]=(a,c]。
int x=find(a); //a的树根
int y=find(b); //b的树根
if(x==y)
{
if((sum[a]-sum[b])!=c)
cnt++;
}
else
{
pre[x]=y; //将含a的树移到含b的树上
//a到x的距离为sum[a],b到y的距离为sum[b],a到b的距离为c
sum[x]=sum[b]+c-sum[a]; //公式看下边连接
}
}
printf("%d\n",cnt);
}
return 0;
}
sum[x] = sum[b] - sum[a] + v 讲解
本文参考博客