1 条题解
-
0
题目分析
本题需要处理多个区间对,每个区间对包含两个区间。我们需要从每个区间对中选择一个区间,使得所有被选中的区间的并集覆盖的总长度最大化。
算法思路
核心思想
1. 离散化处理:将区间端点映射到较小的范围内,便于处理
2. 差分数组:高效标记区间覆盖情况
3. 前缀和/后缀和:快速计算区间覆盖的统计信息
4. 贪心策略:通过比较不同选择的覆盖范围,确定最优解
算法标签
离散化 (Discretization)
差分数组 (Difference Array)
前缀和 (Prefix Sum)
贪心算法 (Greedy Algorithm)
区间处理 (Interval Processing)
代码解析
1. 数据读取与预处理
void read(long long &x) { // 快速读取整数 }- 使用快速读取函数提高输入效率
2. 离散化处理
// 收集所有区间端点 for (i = 1; i <= n; i++) { x[i * 2 + 1] = l2[i]; x[i * 2 + 2] = r2[i] + 1; } x[1] = 1; x[2] = 1000000001; // 排序并离散化 sort(1, n * 2 + 2); for (i = 1; i <= n * 2 + 2; i++) { if (x[num[i]] != x[num[i - 1]]) { to[num[i]] = to[num[i - 1]] + 1; q[to[num[i - 1]]] = x[num[i]] - x[num[i - 1]]; } else to[num[i]] = to[num[i - 1]]; }-
将所有区间端点收集到数组 x 中
-
对端点进行排序和去重
-
建立映射关系,将原始坐标映射到连续的整数索引
-
记录每个离散化区间段的实际长度
3. 差分数组构建
for (i = 1; i <= n; i++) { lmax[to[i * 2 + 2]] = lmax[to[i * 2 + 2]] + r1[i]; lmin[to[i * 2 + 2]] = lmin[to[i * 2 + 2]] + l1[i]; rmax[to[i * 2 + 1] - 1] = rmax[to[i * 2 + 1] - 1] + r1[i]; rmin[to[i * 2 + 1] - 1] = rmin[to[i * 2 + 1] - 1] + l1[i]; num[to[i * 2 + 1]] = num[to[i * 2 + 1]] + r1[i]; num[to[i * 2 + 2]] = num[to[i * 2 + 2]] - r1[i]; }-
使用差分数组标记区间覆盖情况
-
lmax、lmin、rmax、rmin 分别记录左右边界的最大最小值信息
-
num 数组记录区间覆盖的差分信息
4. 前缀和与后缀和计算
// 前缀和 for (i = 1; i <= 2 * n + 3; i++) { lmax[i] = lmax[i - 1] + lmax[i]; lmin[i] = lmin[i - 1] + lmin[i]; num[i] = num[i - 1] + num[i]; } // 后缀和 for (i = 2 * n + 2; i >= 0; i--) { rmax[i] = rmax[i + 1] + rmax[i]; rmin[i] = rmin[i + 1] + rmin[i]; }-
通过前缀和将差分数组转换为实际的覆盖统计
-
计算从左到右和从右到左的累积信息
5. 结果计算
for (i = 1; i <= 2 * n + 2; i++) { if (num[i] > 0 && lmax[i] + num[i] >= rmin[i] && num[i] + rmax[i] > lmin[i]) { ans = ans + q[i]; } }-
遍历所有离散化后的区间段
-
根据覆盖条件和边界条件判断该区间段是否应该被计入答案
-
累加符合条件的区间段长度
复杂度分析
-
时间复杂度:O(n log n),主要开销在排序操作
-
空间复杂度:O(n),用于存储各种数组
关键点
1. 离散化技巧:将大范围坐标映射到小范围,降低处理复杂度
2. 差分数组:高效处理区间覆盖问题
3. 贪心选择:通过比较不同选择的覆盖效果,确定最优解
该算法通过巧妙的离散化和差分技术,有效地解决了大规模区间选择与覆盖问题。
- 1
信息
- ID
- 3141
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 6
- 已通过
- 2
- 上传者