|
|
#include <bits/stdc++.h>
|
|
|
|
|
|
// http://acm.hdu.edu.cn/showproblem.php?pid=3038
|
|
|
// https://blog.csdn.net/sunmaoxiang/article/details/80959300
|
|
|
|
|
|
// https://blog.csdn.net/qq_41552508/article/details/88636637
|
|
|
// https://yiqzq.blog.csdn.net/article/details/80152561
|
|
|
/**
|
|
|
思路: 很显然带权并查集,我们可以用距离的概念代替和的概念比较好理解一点,d表示x到y的和即x到y的距离;
|
|
|
可以用value[x]表示x到其父亲节点的距离,将正确的距离关系合并到并查集中(错误的当然不能合并到里面啦);
|
|
|
|
|
|
要注意的是这里的x, y是闭区间, 我们不好直接处理, 要先将其变成开区间来, [x, y]等价于(x-1, y]或者[x, y+1);
|
|
|
还有要注意有多组输入(坑爹)......
|
|
|
|
|
|
对于这道题来说,加的权,其实就是用value数组存从i的根(并不一定是1,并有可能被更新)到i的值。
|
|
|
需要注意的是,a到b的这个区间,比如说([1,3],[3,7],如果将这两个数组合并,将会把value[3]算两遍.
|
|
|
这里我们用的是不包括前面的数的办法,即(1,3],(3,7]
|
|
|
|
|
|
|
|
|
题意:有一个数列,不知道数列里的数值,有多个询问,每个询问给出回答一段区间的和,但是有些是对的,有些是错的,保证如果无逻辑错误,
|
|
|
则该回答认为是正确的,问哪些询问是错误的可以忽略。
|
|
|
|
|
|
对于询问区间和其实可以看做是前缀和,区间和也就是前缀和的差值,
|
|
|
[a,b]的和就转换成 b个元素的前缀和与 a-1 个元素的前缀和的差值,因此就转变为元素差值关系问题了,
|
|
|
就可以用并查集与元素权值来判断,每个元素的权值代表其与根元素的值的差。注意读入 a、b 区间,需要对 a-1 和 b 进行合并。
|
|
|
|
|
|
这是并查集很常见的题型。
|
|
|
*/
|
|
|
/**
|
|
|
测试数据
|
|
|
10 5
|
|
|
1 10 100
|
|
|
7 10 28
|
|
|
1 3 32
|
|
|
4 6 41
|
|
|
6 6 1
|
|
|
|
|
|
答案:1
|
|
|
*/
|
|
|
using namespace std;
|
|
|
const int N = 200010;
|
|
|
int fa[N]; //并查集数组
|
|
|
int value[N]; //用一个value[]数组保存从某点到其根节点距离(权值)
|
|
|
int n;//区间[1,n]
|
|
|
int m;//下面有m组数据
|
|
|
int ans;
|
|
|
|
|
|
//路径压缩+修改权值 [带权并查集路径压缩模板]
|
|
|
int find(int x) {
|
|
|
if (x == fa[x])
|
|
|
return x;
|
|
|
else {
|
|
|
int t = fa[x]; //记录原父节点编号
|
|
|
fa[x] = find(fa[x]); //父节点变为根节点,此时value[x]=父节点到根节点的权值
|
|
|
value[x] += value[t]; //当前节点的权值加上原本父节点的权值
|
|
|
return fa[x];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int main() {
|
|
|
//读入,初始化
|
|
|
while (cin >> n >> m) {
|
|
|
for (int i = 0; i <= n; i++) {
|
|
|
fa[i] = i;
|
|
|
value[i] = 0;
|
|
|
}
|
|
|
//输入m组数据
|
|
|
while (m--) {
|
|
|
int l, r, dis;
|
|
|
cin >> l >> r >> dis; //l r v表示[l,r]区间和为v
|
|
|
|
|
|
l--; //这里我们用的是不包括前面的数
|
|
|
int RootA = find(l);
|
|
|
int RootB = find(r);
|
|
|
if (RootA == RootB) {
|
|
|
if (value[l] - value[r] != dis) ans++; //每输入一组数据,判断此组条件是否与前面冲突,输出冲突的数据的个数
|
|
|
} else {
|
|
|
fa[RootA] = RootB;
|
|
|
value[RootA] = -value[l] + value[r] + dis; //并查集的权值计算
|
|
|
}
|
|
|
}
|
|
|
cout << ans << endl;
|
|
|
}
|
|
|
return 0;
|
|
|
} |