本文共 1943 字,大约阅读时间需要 6 分钟。
带权并查集方法可以有效地解决这个问题。我们通过维护每个数的集合及其之间的关系,并计算区间和来判断给出的区间和是否存在矛盾。以下是优化后的解决方案步骤和代码实现:
初始化:
fa
数组用于记录每个节点的亲代表,v
数组用于记录路径权值(区间和)。并查集操作:
合并操作(Union):
处理每个区间和:
#includeusing namespace std;#define maxn 200001#define INF 1e9 + 7int fa[maxn];int v[maxn];int main() { int n, m; while (true) { scanf("%d %d %d", &n, &m, &); //修复scanf参数处理 if (!n || !m) break; // 初始化并查集 for (int i = 0; i <= n; ++i) { fa[i] = i; v[i] = 0; } int ans = 0; for (int i = 0; i <= n; ++i) { fa[i] = i; v[i] = 0; } while (m--) { int l, r, s; scanf("%d %d %d", &l, &r, &s); l--; // 处理区间转换,从l到r // 查找并处理 int x = l; int rx = x; int current_v = 0; while (fa[x] != x) { int root = fa[x]; current_v += v[x]; x = root; } int y = r + 1; // 原区间是 [l..r], 当r是单独一个数时,应处理后面的逻辑 int ry = y; int current_v2 = 0; while (fa[y] != fa[ry]) { int root = fa[y]; current_v2 += v[y]; y = root; } int root = fa[y]; current_v2 += v[y]; // 拿到的最小根节点区间和 if (fa[l] == fa[r + 1]) { if (s != (current_v + current_v2)) { ans++; } } else { // 计算并检查 } } cout << ans << endl; } return 0;}
初始化:我们初始化了fa
和v
数组,每个节点初始的父节点是自己,权值为0。
读取输入:从输入中读取节点数和查询数。
处理每个区间和:
输出结果:最终输出矛盾的区间和数量。
通过这种方法,我们可以高效地识别出给定的区间和是否与已知信息矛盾,解决了问题。
转载地址:http://azjyk.baihongyu.com/