一、问题描述
二、输入、输出样例
输入
5 3 3
1 5 15
4 5 9
2 3 5
1 5
1 3
1 2
输出
15
6
UNKNOWN
三、评测用例规模与约定
四、运用的知识点
数据结构:并查集 + 搜索
五、解题代码(+注解)
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
Scanner scannner = new Scanner(System.in);
int N = scannner.nextInt();// 数组长度
int M = scannner.nextInt();// 已知的部分和数量
int Q = scannner.nextInt();// 询问的部分和数量
int[] parent = new int[N + 1];// 并查集的父节点
long[] sum = new long[N + 1];// 存储区间和
for (int i = 1; i <= N; i++) {
parent[i] = i;// 初始化父结点为自己
}
while (M-- > 0) {// 处理已知的部分和
int l = scannner.nextInt();// 左
int r = scannner.nextInt();// 右
long s = scannner.nextLong();// 区间和
int rootL = find(l - 1, parent, sum); // 找到 l-1 的根
int rootR = find(r, parent, sum); // 找到 r 的根
// 合并操作
parent[rootL] = rootR;
sum[rootL] = sum[r] - s - sum[l - 1]; // 更新合并后的节点的和
// 更新以rootL为根的和 = 0~r - s - 0~(r-1)
}
while (Q-- > 0) {// 处理查询
int l = scannner.nextInt();
int r = scannner.nextInt();
int rootL = find(l - 1, parent, sum); // 找到 l-1 的根
int rootR = find(r, parent, sum); // 找到 r 的根
if (rootL != rootR) {
System.out.println("UNKNOWN"); // 根不同,返回 UNKNOWN
} else {
System.out.println(sum[r] - sum[l - 1]); // 输出区间和
}
}
scannner.close();
}
// 查找并压缩路径
static int find(int x, int[] parent, long[] sum) {
if (parent[x] != x) {
int originalParent = parent[x];
parent[x] = find(parent[x], parent, sum); // 路径压缩
sum[x] += sum[originalParent]; // 更新当前节点的和
// 更新节点x的和 = 原来的和 + 它的原父节点的和
}
return parent[x]; // 返回根节点
}
}