1. 问题背景与核心思路
这道蓝桥杯题目要求我们根据已知的若干区间和,推导出其他区间的和值。题目给出了一个长度为N的整数数列A₁到Aₙ,但我们并不知道每个元素的具体值,只知道M个区间[lᵢ,rᵢ]的和Sᵢ。现在有Q个查询,每个查询给出一个区间[l,r],要求输出这个区间的和,如果无法确定则输出UNKNOWN。
1.1 问题转化与图论建模
这个问题的核心在于如何利用已知的部分和关系来推导未知的部分和。我们可以将这个问题转化为图论中的路径求和问题:
-
对于每个已知的区间和A[left...r]=S,我们可以建立两条有向边:
- 从left-1指向r,边权为+S
- 从r指向left-1,边权为-S
-
这样,如果我们想要求A[i...j-1]的和,就相当于在图中寻找从i到j的路径,并将路径上的边权相加。
-
如果i和j不在同一个连通分量中,说明我们无法通过已知信息推导出这个区间的和,应该返回UNKNOWN。
1.2 算法选择与复杂度分析
考虑到题目中的数据规模(N,M,Q≤10⁵),我们需要一个高效的算法。这里提供了几种解决方案:
-
DFS/BFS遍历:对每个连通分量进行遍历,记录每个节点到根节点的"距离"(即前缀和)。查询时检查两点是否连通,若连通则计算两点"距离"之差。
-
并查集(Union-Find):在合并集合的同时维护节点间的相对关系。这种方法可以高效处理连通性查询。
-
树上倍增与ST表:对于树形结构,可以预处理每个节点的2^k级祖先和对应的路径和,实现O(logN)的查询。
在实际编码中,DFS/BFS方法实现简单且时间复杂度为O(N+M+Q),能够很好地满足题目要求。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 详细算法实现
2.1 图的构建与预处理
首先我们需要构建图的邻接表表示:
cpp复制vector<vector<pair<int, long long>>> adj(N + 1);
for (auto [left, r, s] : sum) {
left--;
adj[left].emplace_back(r, s);
adj[r].emplace_back(left, -s);
}
这里有几个关键点需要注意:
- 我们将区间[left,r]转化为节点left-1和r之间的边
- 同时建立正反两条边,保证关系的双向性
- 使用long long类型存储和值,因为Sᵢ的范围可能很大(±10¹²)
2.2 连通分量处理与前缀和计算
接下来我们需要处理各个连通分量,并为每个节点计算前缀和:
cpp复制vector<unordered_map<int, long long>> prefix(N + 1);
vector<int> component(N + 1, -1);
int region = -1;
for (int i = 0; i <= N; i++) {
if (component[i] != -1) continue;
region++;
auto& pre = prefix[region];
function<void(int, long long)> dfs = [&](int cur, long long sum) {
if (pre.count(cur)) return;
pre[cur] = sum;
compon
