1 条题解
-
0
题解
问题分析
这是一个差分约束系统问题。我们需要根据区间第 小的约束条件,构造一个二进制数组。
关键观察
- 前缀和转化:定义前缀和
- 约束转化:区间 中 的个数为
- 第 小值约束:
- 如果第 小是 ,说明 的数量至少为 ,即 的数量最多为
- 如果第 小是 ,说明 的数量至少为
算法思路
差分约束系统 + SPFA 判负环:
约束条件转化
- 基本约束:
- 第 小为 :
- 第 小为 :
图构建
- 节点:
- 边:
- ,权值 ()
- ,权值 ()
- 根据约束条件添加相应边
核心代码逻辑
图构建
// 基本约束 for (int i = 1; i <= n; ++i) { E[i - 1].emplace_back(i, 1); // S[i] - S[i-1] <= 1 E[i].emplace_back(i - 1, 0); // S[i-1] - S[i] <= 0 } // 约束条件转化 if (v == 0) { E[l - 1].emplace_back(r, r - l + 1 - k); // S[r] - S[l-1] <= (r-l+1)-k } else { E[r].emplace_back(l - 1, -(r - l + 1 - k + 1)); // S[l-1] - S[r] <= -((r-l+1)-k+1) }SPFA 求解
std::vector<int> dist(n + 1, 0x3fffffff), inqueue(n + 1, 0), cnt(n + 1, 0); std::queue<int> q; dist[0] = 0; q.push(0); while (!q.empty()) { int u = q.front(); q.pop(); inqueue[u] = 0; for (auto &[v, w] : E[u]) { if (dist[v] > dist[u] + w) { dist[v] = dist[u] + w; cnt[v]++; if (cnt[v] > n) { // 负环检测 puts("-1"); return 0; } if (!inqueue[v]) { q.push(v); inqueue[v] = 1; } } } }算法步骤
- 读入 和约束条件
- 构建图:根据约束条件建立差分约束系统
- SPFA求解:计算最短路径,检测负环
- 输出结果:根据 还原原数组
- 无解判断:发现负环则输出
复杂度分析
- 图构建:
- SPFA:最坏 ,在 时可接受
- 总复杂度:
样例验证
样例输入:
4 5 0 1 2 1 0 2 2 0 2 2 1 0 0 1 1 0 1 2 1 0求解过程:
- 前缀和
- 原数组 ✓
算法标签
- 差分约束系统
- 图论
- 最短路径
- SPFA算法
- 负环检测
- 前缀和技巧
- 1
信息
- ID
- 3983
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者