You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

85 lines
3.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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;
}